summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--packages/backend/src/server/api/EndpointsModule.ts4
-rw-r--r--packages/backend/src/server/api/endpoints.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/users/stats.ts228
-rw-r--r--packages/frontend/src/pages/settings/account-stats.vue146
-rw-r--r--packages/frontend/src/pages/settings/other.vue2
-rw-r--r--packages/frontend/src/router.ts4
-rw-r--r--packages/misskey-js/etc/misskey-js.api.md4
-rw-r--r--packages/misskey-js/src/api.types.ts1
9 files changed, 1 insertions, 391 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f75f9f6b3c..45dc0e3c90 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@
### General
- エラー時や項目が存在しないときなどのアイコン画像をサーバー管理者が設定できるように
- ロールが付与されているユーザーリストを非公開にできるように
+- サーバーの負荷が非常に高いため、ユーザー統計表示機能を削除しました
### Client
- Fix: タブがバックグラウンドでもstreamが切断されないように
diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts
index 1e32e9988d..d1ff3fe925 100644
--- a/packages/backend/src/server/api/EndpointsModule.ts
+++ b/packages/backend/src/server/api/EndpointsModule.ts
@@ -333,7 +333,6 @@ import * as ep___users_reportAbuse from './endpoints/users/report-abuse.js';
import * as ep___users_searchByUsernameAndHost from './endpoints/users/search-by-username-and-host.js';
import * as ep___users_search from './endpoints/users/search.js';
import * as ep___users_show from './endpoints/users/show.js';
-import * as ep___users_stats from './endpoints/users/stats.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___fetchRss from './endpoints/fetch-rss.js';
@@ -674,7 +673,6 @@ const $users_reportAbuse: Provider = { provide: 'ep:users/report-abuse', useClas
const $users_searchByUsernameAndHost: Provider = { provide: 'ep:users/search-by-username-and-host', useClass: ep___users_searchByUsernameAndHost.default };
const $users_search: Provider = { provide: 'ep:users/search', useClass: ep___users_search.default };
const $users_show: Provider = { provide: 'ep:users/show', useClass: ep___users_show.default };
-const $users_stats: Provider = { provide: 'ep:users/stats', useClass: ep___users_stats.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 $fetchRss: Provider = { provide: 'ep:fetch-rss', useClass: ep___fetchRss.default };
@@ -1019,7 +1017,6 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$users_searchByUsernameAndHost,
$users_search,
$users_show,
- $users_stats,
$users_achievements,
$users_updateMemo,
$fetchRss,
@@ -1356,7 +1353,6 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$users_searchByUsernameAndHost,
$users_search,
$users_show,
- $users_stats,
$users_achievements,
$users_updateMemo,
$fetchRss,
diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts
index 7e678a6404..94206ef870 100644
--- a/packages/backend/src/server/api/endpoints.ts
+++ b/packages/backend/src/server/api/endpoints.ts
@@ -333,7 +333,6 @@ import * as ep___users_reportAbuse from './endpoints/users/report-abuse.js';
import * as ep___users_searchByUsernameAndHost from './endpoints/users/search-by-username-and-host.js';
import * as ep___users_search from './endpoints/users/search.js';
import * as ep___users_show from './endpoints/users/show.js';
-import * as ep___users_stats from './endpoints/users/stats.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___fetchRss from './endpoints/fetch-rss.js';
@@ -672,7 +671,6 @@ const eps = [
['users/search-by-username-and-host', ep___users_searchByUsernameAndHost],
['users/search', ep___users_search],
['users/show', ep___users_show],
- ['users/stats', ep___users_stats],
['users/achievements', ep___users_achievements],
['users/update-memo', ep___users_updateMemo],
['fetch-rss', ep___fetchRss],
diff --git a/packages/backend/src/server/api/endpoints/users/stats.ts b/packages/backend/src/server/api/endpoints/users/stats.ts
deleted file mode 100644
index 7479793afe..0000000000
--- a/packages/backend/src/server/api/endpoints/users/stats.ts
+++ /dev/null
@@ -1,228 +0,0 @@
-import { Inject, Injectable } from '@nestjs/common';
-import { awaitAll } from '@/misc/prelude/await-all.js';
-import { Endpoint } from '@/server/api/endpoint-base.js';
-import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
-import { DI } from '@/di-symbols.js';
-import type { UsersRepository, NotesRepository, FollowingsRepository, DriveFilesRepository, NoteReactionsRepository, PageLikesRepository, NoteFavoritesRepository, PollVotesRepository } from '@/models/index.js';
-import { ApiError } from '../../error.js';
-
-export const meta = {
- tags: ['users'],
-
- requireCredential: false,
-
- description: 'Show statistics about a user.',
-
- errors: {
- noSuchUser: {
- message: 'No such user.',
- code: 'NO_SUCH_USER',
- id: '9e638e45-3b25-4ef7-8f95-07e8498f1819',
- },
- },
-
- res: {
- type: 'object',
- optional: false, nullable: false,
- properties: {
- notesCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- repliesCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- renotesCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- repliedCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- renotedCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- pollVotesCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- pollVotedCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- localFollowingCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- remoteFollowingCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- localFollowersCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- remoteFollowersCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- followingCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- followersCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- sentReactionsCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- receivedReactionsCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- noteFavoritesCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- pageLikesCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- pageLikedCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- driveFilesCount: {
- type: 'integer',
- optional: false, nullable: false,
- },
- driveUsage: {
- type: 'integer',
- optional: false, nullable: false,
- description: 'Drive usage in bytes',
- },
- },
- },
-} as const;
-
-export const paramDef = {
- type: 'object',
- properties: {
- userId: { type: 'string', format: 'misskey:id' },
- },
- required: ['userId'],
-} as const;
-
-// eslint-disable-next-line import/no-default-export
-@Injectable()
-export default class extends Endpoint<typeof meta, typeof paramDef> {
- constructor(
- @Inject(DI.usersRepository)
- private usersRepository: UsersRepository,
-
- @Inject(DI.notesRepository)
- private notesRepository: NotesRepository,
-
- @Inject(DI.followingsRepository)
- private followingsRepository: FollowingsRepository,
-
- @Inject(DI.driveFilesRepository)
- private driveFilesRepository: DriveFilesRepository,
-
- @Inject(DI.noteReactionsRepository)
- private noteReactionsRepository: NoteReactionsRepository,
-
- @Inject(DI.pageLikesRepository)
- private pageLikesRepository: PageLikesRepository,
-
- @Inject(DI.noteFavoritesRepository)
- private noteFavoritesRepository: NoteFavoritesRepository,
-
- @Inject(DI.pollVotesRepository)
- private pollVotesRepository: PollVotesRepository,
-
- private driveFileEntityService: DriveFileEntityService,
- ) {
- super(meta, paramDef, async (ps, me) => {
- const user = await this.usersRepository.findOneBy({ id: ps.userId });
- if (user == null) {
- throw new ApiError(meta.errors.noSuchUser);
- }
-
- const result = await awaitAll({
- notesCount: this.notesRepository.createQueryBuilder('note')
- .where('note.userId = :userId', { userId: user.id })
- .getCount(),
- repliesCount: this.notesRepository.createQueryBuilder('note')
- .where('note.userId = :userId', { userId: user.id })
- .andWhere('note.replyId IS NOT NULL')
- .getCount(),
- renotesCount: this.notesRepository.createQueryBuilder('note')
- .where('note.userId = :userId', { userId: user.id })
- .andWhere('note.renoteId IS NOT NULL')
- .getCount(),
- repliedCount: this.notesRepository.createQueryBuilder('note')
- .where('note.replyUserId = :userId', { userId: user.id })
- .getCount(),
- renotedCount: this.notesRepository.createQueryBuilder('note')
- .where('note.renoteUserId = :userId', { userId: user.id })
- .getCount(),
- pollVotesCount: this.pollVotesRepository.createQueryBuilder('vote')
- .where('vote.userId = :userId', { userId: user.id })
- .getCount(),
- pollVotedCount: this.pollVotesRepository.createQueryBuilder('vote')
- .innerJoin('vote.note', 'note')
- .where('note.userId = :userId', { userId: user.id })
- .getCount(),
- localFollowingCount: this.followingsRepository.createQueryBuilder('following')
- .where('following.followerId = :userId', { userId: user.id })
- .andWhere('following.followeeHost IS NULL')
- .getCount(),
- remoteFollowingCount: this.followingsRepository.createQueryBuilder('following')
- .where('following.followerId = :userId', { userId: user.id })
- .andWhere('following.followeeHost IS NOT NULL')
- .getCount(),
- localFollowersCount: this.followingsRepository.createQueryBuilder('following')
- .where('following.followeeId = :userId', { userId: user.id })
- .andWhere('following.followerHost IS NULL')
- .getCount(),
- remoteFollowersCount: this.followingsRepository.createQueryBuilder('following')
- .where('following.followeeId = :userId', { userId: user.id })
- .andWhere('following.followerHost IS NOT NULL')
- .getCount(),
- sentReactionsCount: this.noteReactionsRepository.createQueryBuilder('reaction')
- .where('reaction.userId = :userId', { userId: user.id })
- .getCount(),
- receivedReactionsCount: this.noteReactionsRepository.createQueryBuilder('reaction')
- .innerJoin('reaction.note', 'note')
- .where('note.userId = :userId', { userId: user.id })
- .getCount(),
- noteFavoritesCount: this.noteFavoritesRepository.createQueryBuilder('favorite')
- .where('favorite.userId = :userId', { userId: user.id })
- .getCount(),
- pageLikesCount: this.pageLikesRepository.createQueryBuilder('like')
- .where('like.userId = :userId', { userId: user.id })
- .getCount(),
- pageLikedCount: this.pageLikesRepository.createQueryBuilder('like')
- .innerJoin('like.page', 'page')
- .where('page.userId = :userId', { userId: user.id })
- .getCount(),
- driveFilesCount: this.driveFilesRepository.createQueryBuilder('file')
- .where('file.userId = :userId', { userId: user.id })
- .getCount(),
- driveUsage: this.driveFileEntityService.calcDriveUsageOf(user),
- });
-
- return {
- ...result,
- followingCount: result.localFollowingCount + result.remoteFollowingCount,
- followersCount: result.localFollowersCount + result.remoteFollowersCount,
- };
- });
- }
-}
diff --git a/packages/frontend/src/pages/settings/account-stats.vue b/packages/frontend/src/pages/settings/account-stats.vue
deleted file mode 100644
index a0f1541b40..0000000000
--- a/packages/frontend/src/pages/settings/account-stats.vue
+++ /dev/null
@@ -1,146 +0,0 @@
-<template>
-<div class="_gaps_m">
- <FormSection v-if="stats" first>
- <template #label>{{ i18n.ts.statistics }}</template>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.notesCount }}</template>
- <template #value>{{ number(stats.notesCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.repliesCount }}</template>
- <template #value>{{ number(stats.repliesCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.renotesCount }}</template>
- <template #value>{{ number(stats.renotesCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.repliedCount }}</template>
- <template #value>{{ number(stats.repliedCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.renotedCount }}</template>
- <template #value>{{ number(stats.renotedCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.pollVotesCount }}</template>
- <template #value>{{ number(stats.pollVotesCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.pollVotedCount }}</template>
- <template #value>{{ number(stats.pollVotedCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.sentReactionsCount }}</template>
- <template #value>{{ number(stats.sentReactionsCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.receivedReactionsCount }}</template>
- <template #value>{{ number(stats.receivedReactionsCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.noteFavoritesCount }}</template>
- <template #value>{{ number(stats.noteFavoritesCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.followingCount }}</template>
- <template #value>{{ number(stats.followingCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.followingCount }} ({{ i18n.ts.local }})</template>
- <template #value>{{ number(stats.localFollowingCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.followingCount }} ({{ i18n.ts.remote }})</template>
- <template #value>{{ number(stats.remoteFollowingCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.followersCount }}</template>
- <template #value>{{ number(stats.followersCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.followersCount }} ({{ i18n.ts.local }})</template>
- <template #value>{{ number(stats.localFollowersCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.followersCount }} ({{ i18n.ts.remote }})</template>
- <template #value>{{ number(stats.remoteFollowersCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.pageLikesCount }}</template>
- <template #value>{{ number(stats.pageLikesCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.pageLikedCount }}</template>
- <template #value>{{ number(stats.pageLikedCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.driveFilesCount }}</template>
- <template #value>{{ number(stats.driveFilesCount) }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>{{ i18n.ts.driveUsage }}</template>
- <template #value>{{ bytes(stats.driveUsage) }}</template>
- </MkKeyValue>
- </FormSection>
-
- <FormSection>
- <template #label>{{ i18n.ts.other }}</template>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>emailVerified</template>
- <template #value>{{ $i.emailVerified ? i18n.ts.yes : i18n.ts.no }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>twoFactorEnabled</template>
- <template #value>{{ $i.twoFactorEnabled ? i18n.ts.yes : i18n.ts.no }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>securityKeys</template>
- <template #value>{{ $i.securityKeys ? i18n.ts.yes : i18n.ts.no }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>usePasswordLessLogin</template>
- <template #value>{{ $i.usePasswordLessLogin ? i18n.ts.yes : i18n.ts.no }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>isModerator</template>
- <template #value>{{ $i.isModerator ? i18n.ts.yes : i18n.ts.no }}</template>
- </MkKeyValue>
- <MkKeyValue oneline style="margin: 1em 0;">
- <template #key>isAdmin</template>
- <template #value>{{ $i.isAdmin ? i18n.ts.yes : i18n.ts.no }}</template>
- </MkKeyValue>
- </FormSection>
-</div>
-</template>
-
-<script lang="ts" setup>
-import { onMounted, ref } from 'vue';
-import FormSection from '@/components/form/section.vue';
-import MkKeyValue from '@/components/MkKeyValue.vue';
-import * as os from '@/os';
-import number from '@/filters/number';
-import bytes from '@/filters/bytes';
-import { $i } from '@/account';
-import { i18n } from '@/i18n';
-import { definePageMetadata } from '@/scripts/page-metadata';
-
-const stats = ref<any>({});
-
-onMounted(() => {
- os.api('users/stats', {
- userId: $i!.id,
- }).then(response => {
- stats.value = response;
- });
-});
-
-const headerActions = $computed(() => []);
-
-const headerTabs = $computed(() => []);
-
-definePageMetadata({
- title: i18n.ts.accountInfo,
- icon: 'ti ti-info-circle',
-});
-</script>
diff --git a/packages/frontend/src/pages/settings/other.vue b/packages/frontend/src/pages/settings/other.vue
index 0b73780a8b..3d8bb59277 100644
--- a/packages/frontend/src/pages/settings/other.vue
+++ b/packages/frontend/src/pages/settings/other.vue
@@ -26,8 +26,6 @@
<template #key>{{ i18n.ts.registeredDate }}</template>
<template #value><MkTime :time="$i.createdAt" mode="detail"/></template>
</MkKeyValue>
-
- <FormLink to="/settings/account-stats"><template #icon><i class="ti ti-info-circle"></i></template>{{ i18n.ts.statistics }}</FormLink>
</div>
</MkFolder>
diff --git a/packages/frontend/src/router.ts b/packages/frontend/src/router.ts
index a95e8e6485..fe9bc5938e 100644
--- a/packages/frontend/src/router.ts
+++ b/packages/frontend/src/router.ts
@@ -178,10 +178,6 @@ export const routes = [{
name: 'profile',
component: page(() => import('./pages/settings/accounts.vue')),
}, {
- path: '/account-stats',
- name: 'other',
- component: page(() => import('./pages/settings/account-stats.vue')),
- }, {
path: '/other',
name: 'other',
component: page(() => import('./pages/settings/other.vue')),
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index eddc5cf90c..ca8eee01a1 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -2147,10 +2147,6 @@ export type Endpoints = {
};
};
};
- 'users/stats': {
- req: TODO;
- res: TODO;
- };
};
declare namespace entities {
diff --git a/packages/misskey-js/src/api.types.ts b/packages/misskey-js/src/api.types.ts
index cc88c4b1a4..b8c59e7b15 100644
--- a/packages/misskey-js/src/api.types.ts
+++ b/packages/misskey-js/src/api.types.ts
@@ -602,5 +602,4 @@ export type Endpoints = {
$default: UserDetailed;
};
}; };
- 'users/stats': { req: TODO; res: TODO; };
};