summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api/endpoints
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-10-21 14:18:53 +0900
committerGitHub <noreply@github.com>2023-10-21 14:18:53 +0900
commit3043b5256d7f9d9228035b0af9943027e0222dd4 (patch)
treed90296222000ca6f11e1ca26f940bc136b913e0f /packages/backend/src/server/api/endpoints
parentMerge pull request #12011 from misskey-dev/develop (diff)
parentNew Crowdin updates (#12094) (diff)
downloadmisskey-3043b5256d7f9d9228035b0af9943027e0222dd4.tar.gz
misskey-3043b5256d7f9d9228035b0af9943027e0222dd4.tar.bz2
misskey-3043b5256d7f9d9228035b0af9943027e0222dd4.zip
Merge pull request #12060 from misskey-dev/develop
Release: 2023.10.2
Diffstat (limited to 'packages/backend/src/server/api/endpoints')
-rw-r--r--packages/backend/src/server/api/endpoints/admin/ad/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/admin/announcements/create.ts1
-rw-r--r--packages/backend/src/server/api/endpoints/admin/announcements/list.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/drive/show-file.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/emoji/copy.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/get-user-ips.ts5
-rw-r--r--packages/backend/src/server/api/endpoints/admin/invite/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/admin/invite/list.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/meta.ts11
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/users.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/show-user.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/show-users.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/update-meta.ts60
-rw-r--r--packages/backend/src/server/api/endpoints/antennas/create.ts5
-rw-r--r--packages/backend/src/server/api/endpoints/antennas/notes.ts10
-rw-r--r--packages/backend/src/server/api/endpoints/antennas/update.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/app/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/auth/accept.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/auth/session/generate.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/channels/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/channels/favorite.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/channels/follow.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/channels/timeline.ts10
-rw-r--r--packages/backend/src/server/api/endpoints/clips/favorite.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/drive/files.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/drive/folders/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/federation/instances.ts18
-rw-r--r--packages/backend/src/server/api/endpoints/flash/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/flash/like.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/following/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/gallery/posts/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/gallery/posts/like.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/hashtags/users.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/i/apps.ts9
-rw-r--r--packages/backend/src/server/api/endpoints/i/import-following.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/i/registry/set.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/i/webhooks/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/invite/create.ts5
-rw-r--r--packages/backend/src/server/api/endpoints/invite/limit.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/miauth/gen-token.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/notes/favorites/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts161
-rw-r--r--packages/backend/src/server/api/endpoints/notes/local-timeline.ts120
-rw-r--r--packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/notes/polls/vote.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/notes/timeline.ts156
-rw-r--r--packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts18
-rw-r--r--packages/backend/src/server/api/endpoints/pages/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/pages/like.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/promo/read.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/renote-mute/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/request-reset-password.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/reset-password.ts5
-rw-r--r--packages/backend/src/server/api/endpoints/roles/notes.ts10
-rw-r--r--packages/backend/src/server/api/endpoints/sw/register.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/users.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/users/lists/create.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/users/lists/favorite.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/users/notes.ts19
-rw-r--r--packages/backend/src/server/api/endpoints/users/report-abuse.ts3
-rw-r--r--packages/backend/src/server/api/endpoints/users/update-memo.ts2
63 files changed, 500 insertions, 267 deletions
diff --git a/packages/backend/src/server/api/endpoints/admin/ad/create.ts b/packages/backend/src/server/api/endpoints/admin/ad/create.ts
index e48dffecf4..17f792639b 100644
--- a/packages/backend/src/server/api/endpoints/admin/ad/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/ad/create.ts
@@ -44,8 +44,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
) {
super(meta, paramDef, async (ps, me) => {
const ad = await this.adsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
expiresAt: new Date(ps.expiresAt),
startsAt: new Date(ps.startsAt),
dayOfWeek: ps.dayOfWeek,
diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
index 262b36b9a4..253a29cf5a 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
@@ -71,7 +71,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
) {
super(meta, paramDef, async (ps, me) => {
const { raw, packed } = await this.announcementService.create({
- createdAt: new Date(),
updatedAt: null,
title: ps.title,
text: ps.text,
diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
index c82e702eef..fefc379c00 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
@@ -9,6 +9,7 @@ import type { MiAnnouncement } from '@/models/Announcement.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { QueryService } from '@/core/QueryService.js';
import { DI } from '@/di-symbols.js';
+import { IdService } from '@/core/IdService.js';
export const meta = {
tags: ['admin'],
@@ -81,6 +82,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private announcementReadsRepository: AnnouncementReadsRepository,
private queryService: QueryService,
+ private idService: IdService,
) {
super(meta, paramDef, async (ps, me) => {
const query = this.queryService.makePaginationQuery(this.announcementsRepository.createQueryBuilder('announcement'), ps.sinceId, ps.untilId);
@@ -102,7 +104,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
return announcements.map(announcement => ({
id: announcement.id,
- createdAt: announcement.createdAt.toISOString(),
+ createdAt: this.idService.parse(announcement.id).date.toISOString(),
updatedAt: announcement.updatedAt?.toISOString() ?? null,
title: announcement.title,
text: announcement.text,
diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
index 7fb5342f8d..4e5320007e 100644
--- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
+++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
@@ -8,6 +8,7 @@ import type { DriveFilesRepository, UsersRepository } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { DI } from '@/di-symbols.js';
import { RoleService } from '@/core/RoleService.js';
+import { IdService } from '@/core/IdService.js';
import { ApiError } from '../../../error.js';
export const meta = {
@@ -163,6 +164,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private usersRepository: UsersRepository,
private roleService: RoleService,
+ private idService: IdService,
) {
super(meta, paramDef, async (ps, me) => {
const file = ps.fileId ? await this.driveFilesRepository.findOneBy({ id: ps.fileId }) : await this.driveFilesRepository.findOne({
@@ -212,7 +214,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
type: file.type,
name: file.name,
md5: file.md5,
- createdAt: file.createdAt.toISOString(),
+ createdAt: this.idService.parse(file.id).date.toISOString(),
requestIp: iAmModerator ? file.requestIp : null,
requestHeaders: iAmModerator && !ownerIsModerator ? file.requestHeaders : null,
};
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
index c5f986ff02..a65e4e7624 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
@@ -79,7 +79,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
const copied = await this.emojisRepository.insert({
- id: this.idService.genId(),
+ id: this.idService.gen(),
updatedAt: new Date(),
name: emoji.name,
host: null,
diff --git a/packages/backend/src/server/api/endpoints/admin/get-user-ips.ts b/packages/backend/src/server/api/endpoints/admin/get-user-ips.ts
index cf94c998fa..6afa824703 100644
--- a/packages/backend/src/server/api/endpoints/admin/get-user-ips.ts
+++ b/packages/backend/src/server/api/endpoints/admin/get-user-ips.ts
@@ -7,6 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
import type { UserIpsRepository } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { DI } from '@/di-symbols.js';
+import { IdService } from '@/core/IdService.js';
export const meta = {
tags: ['admin'],
@@ -28,11 +29,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
constructor(
@Inject(DI.userIpsRepository)
private userIpsRepository: UserIpsRepository,
+
+ private idService: IdService,
) {
super(meta, paramDef, async (ps, me) => {
const ips = await this.userIpsRepository.find({
where: { userId: ps.userId },
- order: { createdAt: 'DESC' },
+ order: { id: 'DESC' },
take: 30,
});
diff --git a/packages/backend/src/server/api/endpoints/admin/invite/create.ts b/packages/backend/src/server/api/endpoints/admin/invite/create.ts
index 2cc5ab6e35..4a22fd4824 100644
--- a/packages/backend/src/server/api/endpoints/admin/invite/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/invite/create.ts
@@ -72,8 +72,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
for (let i = 0; i < ps.count; i++) {
ticketsPromises.push(this.registrationTicketsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : null,
code: generateInviteCode(),
}).then(x => this.registrationTicketsRepository.findOneByOrFail(x.identifiers[0])));
diff --git a/packages/backend/src/server/api/endpoints/admin/invite/list.ts b/packages/backend/src/server/api/endpoints/admin/invite/list.ts
index a20a51121a..f25d3fcb33 100644
--- a/packages/backend/src/server/api/endpoints/admin/invite/list.ts
+++ b/packages/backend/src/server/api/endpoints/admin/invite/list.ts
@@ -56,8 +56,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
switch (ps.sort) {
- case '+createdAt': query.orderBy('ticket.createdAt', 'DESC'); break;
- case '-createdAt': query.orderBy('ticket.createdAt', 'ASC'); break;
+ case '+createdAt': query.orderBy('ticket.id', 'DESC'); break;
+ case '-createdAt': query.orderBy('ticket.id', 'ASC'); break;
case '+usedAt': query.orderBy('ticket.usedAt', 'DESC', 'NULLS LAST'); break;
case '-usedAt': query.orderBy('ticket.usedAt', 'ASC', 'NULLS FIRST'); break;
default: query.orderBy('ticket.id', 'DESC'); break;
diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts
index 5a74456ab0..f294934344 100644
--- a/packages/backend/src/server/api/endpoints/admin/meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/meta.ts
@@ -105,6 +105,16 @@ export const meta = {
type: 'boolean',
optional: false, nullable: false,
},
+ silencedHosts: {
+ type: "array",
+ optional: true,
+ nullable: false,
+ items: {
+ type: "string",
+ optional: false,
+ nullable: false,
+ },
+ },
pinnedUsers: {
type: 'array',
optional: false, nullable: false,
@@ -367,6 +377,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
pinnedUsers: instance.pinnedUsers,
hiddenTags: instance.hiddenTags,
blockedHosts: instance.blockedHosts,
+ silencedHosts: instance.silencedHosts,
sensitiveWords: instance.sensitiveWords,
preservedUsernames: instance.preservedUsernames,
hcaptchaSecretKey: instance.hcaptchaSecretKey,
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/users.ts b/packages/backend/src/server/api/endpoints/admin/roles/users.ts
index ef5627bc9a..b7f9aa0495 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/users.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/users.ts
@@ -10,6 +10,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import { QueryService } from '@/core/QueryService.js';
import { DI } from '@/di-symbols.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import { IdService } from '@/core/IdService.js';
import { ApiError } from '../../../error.js';
export const meta = {
@@ -49,6 +50,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private queryService: QueryService,
private userEntityService: UserEntityService,
+ private idService: IdService,
) {
super(meta, paramDef, async (ps, me) => {
const role = await this.rolesRepository.findOneBy({
@@ -74,7 +76,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
return await Promise.all(assigns.map(async assign => ({
id: assign.id,
- createdAt: assign.createdAt,
+ createdAt: this.idService.parse(assign.id).date.toISOString(),
user: await this.userEntityService.pack(assign.user!, me, { detail: true }),
expiresAt: assign.expiresAt,
})));
diff --git a/packages/backend/src/server/api/endpoints/admin/show-user.ts b/packages/backend/src/server/api/endpoints/admin/show-user.ts
index 0731413d05..f550c4fd28 100644
--- a/packages/backend/src/server/api/endpoints/admin/show-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/show-user.ts
@@ -9,6 +9,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import { DI } from '@/di-symbols.js';
import { RoleService } from '@/core/RoleService.js';
import { RoleEntityService } from '@/core/entities/RoleEntityService.js';
+import { IdService } from '@/core/IdService.js';
export const meta = {
tags: ['admin'],
@@ -44,6 +45,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private roleService: RoleService,
private roleEntityService: RoleEntityService,
+ private idService: IdService,
) {
super(meta, paramDef, async (ps, me) => {
const [user, profile] = await Promise.all([
@@ -92,7 +94,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
policies: await this.roleService.getUserPolicies(user.id),
roles: await this.roleEntityService.packMany(roles, me),
roleAssigns: roleAssigns.map(a => ({
- createdAt: a.createdAt.toISOString(),
+ createdAt: this.idService.parse(a.id).date.toISOString(),
expiresAt: a.expiresAt ? a.expiresAt.toISOString() : null,
roleId: a.roleId,
})),
diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts
index e89e1a1490..fc810987d2 100644
--- a/packages/backend/src/server/api/endpoints/admin/show-users.ts
+++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts
@@ -99,8 +99,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
switch (ps.sort) {
case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
- case '+createdAt': query.orderBy('user.createdAt', 'DESC'); break;
- case '-createdAt': query.orderBy('user.createdAt', 'ASC'); break;
+ case '+createdAt': query.orderBy('user.id', 'DESC'); break;
+ case '-createdAt': query.orderBy('user.id', 'ASC'); break;
case '+updatedAt': query.orderBy('user.updatedAt', 'DESC', 'NULLS LAST'); break;
case '-updatedAt': query.orderBy('user.updatedAt', 'ASC', 'NULLS FIRST'); break;
case '+lastActiveDate': query.orderBy('user.lastActiveDate', 'DESC', 'NULLS LAST'); break;
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 7db25e659f..f05819b186 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
@@ -20,18 +20,26 @@ export const paramDef = {
type: 'object',
properties: {
disableRegistration: { type: 'boolean', nullable: true },
- pinnedUsers: { type: 'array', nullable: true, items: {
- type: 'string',
- } },
- hiddenTags: { type: 'array', nullable: true, items: {
- type: 'string',
- } },
- blockedHosts: { type: 'array', nullable: true, items: {
- type: 'string',
- } },
- sensitiveWords: { type: 'array', nullable: true, items: {
- type: 'string',
- } },
+ pinnedUsers: {
+ type: 'array', nullable: true, items: {
+ type: 'string',
+ },
+ },
+ hiddenTags: {
+ type: 'array', nullable: true, items: {
+ type: 'string',
+ },
+ },
+ blockedHosts: {
+ type: 'array', nullable: true, items: {
+ type: 'string',
+ },
+ },
+ sensitiveWords: {
+ type: 'array', nullable: true, items: {
+ type: 'string',
+ },
+ },
themeColor: { type: 'string', nullable: true, pattern: '^#[0-9a-fA-F]{6}$' },
mascotImageUrl: { type: 'string', nullable: true },
bannerUrl: { type: 'string', nullable: true },
@@ -67,9 +75,11 @@ export const paramDef = {
proxyAccountId: { type: 'string', format: 'misskey:id', nullable: true },
maintainerName: { type: 'string', nullable: true },
maintainerEmail: { type: 'string', nullable: true },
- langs: { type: 'array', items: {
- type: 'string',
- } },
+ langs: {
+ type: 'array', items: {
+ type: 'string',
+ },
+ },
summalyProxy: { type: 'string', nullable: true },
deeplAuthKey: { type: 'string', nullable: true },
deeplIsPro: { type: 'boolean' },
@@ -86,8 +96,8 @@ export const paramDef = {
tosUrl: { type: 'string', nullable: true },
repositoryUrl: { type: 'string' },
feedbackUrl: { type: 'string' },
- impressumUrl: { type: 'string' },
- privacyPolicyUrl: { type: 'string' },
+ impressumUrl: { type: 'string', nullable: true },
+ privacyPolicyUrl: { type: 'string', nullable: true },
useObjectStorage: { type: 'boolean' },
objectStorageBaseUrl: { type: 'string', nullable: true },
objectStorageBucket: { type: 'string', nullable: true },
@@ -115,6 +125,13 @@ export const paramDef = {
perUserHomeTimelineCacheMax: { type: 'integer' },
perUserListTimelineCacheMax: { type: 'integer' },
notesPerOneAd: { type: 'integer' },
+ silencedHosts: {
+ type: 'array',
+ nullable: true,
+ items: {
+ type: 'string',
+ },
+ },
},
required: [],
} as const;
@@ -147,7 +164,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (Array.isArray(ps.sensitiveWords)) {
set.sensitiveWords = ps.sensitiveWords.filter(Boolean);
}
-
+ if (Array.isArray(ps.silencedHosts)) {
+ let lastValue = '';
+ set.silencedHosts = ps.silencedHosts.sort().filter((h) => {
+ const lv = lastValue;
+ lastValue = h;
+ return h !== '' && h !== lv && !set.blockedHosts?.includes(h);
+ });
+ }
if (ps.themeColor !== undefined) {
set.themeColor = ps.themeColor;
}
diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts
index 15fca4904d..b029493d3a 100644
--- a/packages/backend/src/server/api/endpoints/antennas/create.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/create.ts
@@ -63,6 +63,7 @@ export const paramDef = {
type: 'string',
} },
caseSensitive: { type: 'boolean' },
+ localOnly: { type: 'boolean' },
withReplies: { type: 'boolean' },
withFile: { type: 'boolean' },
notify: { type: 'boolean' },
@@ -112,8 +113,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const now = new Date();
const antenna = await this.antennasRepository.insert({
- id: this.idService.genId(),
- createdAt: now,
+ id: this.idService.gen(now.getTime()),
lastUsedAt: now,
userId: me.id,
name: ps.name,
@@ -123,6 +123,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
excludeKeywords: ps.excludeKeywords,
users: ps.users,
caseSensitive: ps.caseSensitive,
+ localOnly: ps.localOnly,
withReplies: ps.withReplies,
withFile: ps.withFile,
notify: ps.notify,
diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts
index 6d69971e30..9b5911800c 100644
--- a/packages/backend/src/server/api/endpoints/antennas/notes.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts
@@ -12,7 +12,7 @@ import { NoteReadService } from '@/core/NoteReadService.js';
import { DI } from '@/di-symbols.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { IdService } from '@/core/IdService.js';
-import { RedisTimelineService } from '@/core/RedisTimelineService.js';
+import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
import { ApiError } from '../../error.js';
export const meta = {
@@ -70,11 +70,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private noteEntityService: NoteEntityService,
private queryService: QueryService,
private noteReadService: NoteReadService,
- private redisTimelineService: RedisTimelineService,
+ private funoutTimelineService: FunoutTimelineService,
) {
super(meta, paramDef, async (ps, me) => {
- const untilId = ps.untilId ?? (ps.untilDate ? this.idService.genId(new Date(ps.untilDate!)) : null);
- const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.genId(new Date(ps.sinceDate!)) : null);
+ const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null);
+ const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null);
const antenna = await this.antennasRepository.findOneBy({
id: ps.antennaId,
@@ -90,7 +90,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
lastUsedAt: new Date(),
});
- let noteIds = await this.redisTimelineService.get(`antennaTimeline:${antenna.id}`, untilId, sinceId);
+ let noteIds = await this.funoutTimelineService.get(`antennaTimeline:${antenna.id}`, untilId, sinceId);
noteIds = noteIds.slice(0, ps.limit);
if (noteIds.length === 0) {
return [];
diff --git a/packages/backend/src/server/api/endpoints/antennas/update.ts b/packages/backend/src/server/api/endpoints/antennas/update.ts
index 0e98746881..3457bb6f66 100644
--- a/packages/backend/src/server/api/endpoints/antennas/update.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/update.ts
@@ -62,6 +62,7 @@ export const paramDef = {
type: 'string',
} },
caseSensitive: { type: 'boolean' },
+ localOnly: { type: 'boolean' },
withReplies: { type: 'boolean' },
withFile: { type: 'boolean' },
notify: { type: 'boolean' },
@@ -116,6 +117,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
excludeKeywords: ps.excludeKeywords,
users: ps.users,
caseSensitive: ps.caseSensitive,
+ localOnly: ps.localOnly,
withReplies: ps.withReplies,
withFile: ps.withFile,
notify: ps.notify,
diff --git a/packages/backend/src/server/api/endpoints/app/create.ts b/packages/backend/src/server/api/endpoints/app/create.ts
index cb00221506..f89d9823ba 100644
--- a/packages/backend/src/server/api/endpoints/app/create.ts
+++ b/packages/backend/src/server/api/endpoints/app/create.ts
@@ -55,8 +55,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// Create account
const app = await this.appsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
userId: me ? me.id : null,
name: ps.name,
description: ps.description,
diff --git a/packages/backend/src/server/api/endpoints/auth/accept.ts b/packages/backend/src/server/api/endpoints/auth/accept.ts
index 1b1893fd94..e0baeb3565 100644
--- a/packages/backend/src/server/api/endpoints/auth/accept.ts
+++ b/packages/backend/src/server/api/endpoints/auth/accept.ts
@@ -80,8 +80,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const now = new Date();
await this.accessTokensRepository.insert({
- id: this.idService.genId(),
- createdAt: now,
+ id: this.idService.gen(now.getTime()),
lastUsedAt: now,
appId: session.appId,
userId: me.id,
diff --git a/packages/backend/src/server/api/endpoints/auth/session/generate.ts b/packages/backend/src/server/api/endpoints/auth/session/generate.ts
index 8b6a2c213d..6e474c59e0 100644
--- a/packages/backend/src/server/api/endpoints/auth/session/generate.ts
+++ b/packages/backend/src/server/api/endpoints/auth/session/generate.ts
@@ -79,8 +79,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// Create session token document
const doc = await this.authSessionsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
appId: app.id,
token: token,
}).then(x => this.authSessionsRepository.findOneByOrFail(x.identifiers[0]));
diff --git a/packages/backend/src/server/api/endpoints/channels/create.ts b/packages/backend/src/server/api/endpoints/channels/create.ts
index e72120e156..3ba411d28c 100644
--- a/packages/backend/src/server/api/endpoints/channels/create.ts
+++ b/packages/backend/src/server/api/endpoints/channels/create.ts
@@ -80,8 +80,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
const channel = await this.channelsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
userId: me.id,
name: ps.name,
description: ps.description ?? null,
diff --git a/packages/backend/src/server/api/endpoints/channels/favorite.ts b/packages/backend/src/server/api/endpoints/channels/favorite.ts
index 1f78a86dd4..c175718919 100644
--- a/packages/backend/src/server/api/endpoints/channels/favorite.ts
+++ b/packages/backend/src/server/api/endpoints/channels/favorite.ts
@@ -57,8 +57,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
await this.channelFavoritesRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
userId: me.id,
channelId: channel.id,
});
diff --git a/packages/backend/src/server/api/endpoints/channels/follow.ts b/packages/backend/src/server/api/endpoints/channels/follow.ts
index 5a43e8be1b..76ec6be805 100644
--- a/packages/backend/src/server/api/endpoints/channels/follow.ts
+++ b/packages/backend/src/server/api/endpoints/channels/follow.ts
@@ -57,8 +57,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
await this.channelFollowingsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
followerId: me.id,
followeeId: channel.id,
});
diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts
index 2dfcf659d7..fae4249c8a 100644
--- a/packages/backend/src/server/api/endpoints/channels/timeline.ts
+++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts
@@ -12,7 +12,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import ActiveUsersChart from '@/core/chart/charts/active-users.js';
import { DI } from '@/di-symbols.js';
import { IdService } from '@/core/IdService.js';
-import { RedisTimelineService } from '@/core/RedisTimelineService.js';
+import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
import { isUserRelated } from '@/misc/is-user-related.js';
import { CacheService } from '@/core/CacheService.js';
import { ApiError } from '../../error.js';
@@ -69,13 +69,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private idService: IdService,
private noteEntityService: NoteEntityService,
private queryService: QueryService,
- private redisTimelineService: RedisTimelineService,
+ private funoutTimelineService: FunoutTimelineService,
private cacheService: CacheService,
private activeUsersChart: ActiveUsersChart,
) {
super(meta, paramDef, async (ps, me) => {
- const untilId = ps.untilId ?? (ps.untilDate ? this.idService.genId(new Date(ps.untilDate!)) : null);
- const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.genId(new Date(ps.sinceDate!)) : null);
+ const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null);
+ const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null);
const isRangeSpecified = untilId != null && sinceId != null;
const channel = await this.channelsRepository.findOneBy({
@@ -95,7 +95,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
this.cacheService.userMutingsCache.fetch(me.id),
]) : [new Set<string>()];
- let noteIds = await this.redisTimelineService.get(`channelTimeline:${channel.id}`, untilId, sinceId);
+ let noteIds = await this.funoutTimelineService.get(`channelTimeline:${channel.id}`, untilId, sinceId);
noteIds = noteIds.slice(0, ps.limit);
if (noteIds.length > 0) {
diff --git a/packages/backend/src/server/api/endpoints/clips/favorite.ts b/packages/backend/src/server/api/endpoints/clips/favorite.ts
index 6cd34f0a54..015b2cfa85 100644
--- a/packages/backend/src/server/api/endpoints/clips/favorite.ts
+++ b/packages/backend/src/server/api/endpoints/clips/favorite.ts
@@ -74,8 +74,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
await this.clipFavoritesRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
clipId: clip.id,
userId: me.id,
});
diff --git a/packages/backend/src/server/api/endpoints/drive/files.ts b/packages/backend/src/server/api/endpoints/drive/files.ts
index 6f3a62977f..b7e9d12e94 100644
--- a/packages/backend/src/server/api/endpoints/drive/files.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files.ts
@@ -69,8 +69,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
switch (ps.sort) {
- case '+createdAt': query.orderBy('file.createdAt', 'DESC'); break;
- case '-createdAt': query.orderBy('file.createdAt', 'ASC'); break;
+ case '+createdAt': query.orderBy('file.id', 'DESC'); break;
+ case '-createdAt': query.orderBy('file.id', 'ASC'); break;
case '+name': query.orderBy('file.name', 'DESC'); break;
case '-name': query.orderBy('file.name', 'ASC'); break;
case '+size': query.orderBy('file.size', 'DESC'); break;
diff --git a/packages/backend/src/server/api/endpoints/drive/folders/create.ts b/packages/backend/src/server/api/endpoints/drive/folders/create.ts
index bc3a9bbe21..d18199f19b 100644
--- a/packages/backend/src/server/api/endpoints/drive/folders/create.ts
+++ b/packages/backend/src/server/api/endpoints/drive/folders/create.ts
@@ -76,8 +76,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// Create folder
const folder = await this.driveFoldersRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
name: ps.name,
parentId: parent !== null ? parent.id : null,
userId: me.id,
diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts
index be73e5dbb8..c8beefa9c7 100644
--- a/packages/backend/src/server/api/endpoints/federation/instances.ts
+++ b/packages/backend/src/server/api/endpoints/federation/instances.ts
@@ -36,6 +36,7 @@ export const paramDef = {
blocked: { type: 'boolean', nullable: true },
notResponding: { type: 'boolean', nullable: true },
suspended: { type: 'boolean', nullable: true },
+ silenced: { type: "boolean", nullable: true },
federating: { type: 'boolean', nullable: true },
subscribing: { type: 'boolean', nullable: true },
publishing: { type: 'boolean', nullable: true },
@@ -102,6 +103,23 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
}
+ if (typeof ps.silenced === "boolean") {
+ const meta = await this.metaService.fetch(true);
+
+ if (ps.silenced) {
+ if (meta.silencedHosts.length === 0) {
+ return [];
+ }
+ query.andWhere("instance.host IN (:...silences)", {
+ silences: meta.silencedHosts,
+ });
+ } else if (meta.silencedHosts.length > 0) {
+ query.andWhere("instance.host NOT IN (:...silences)", {
+ silences: meta.silencedHosts,
+ });
+ }
+ }
+
if (typeof ps.federating === 'boolean') {
if (ps.federating) {
query.andWhere('((instance.followingCount > 0) OR (instance.followersCount > 0))');
diff --git a/packages/backend/src/server/api/endpoints/flash/create.ts b/packages/backend/src/server/api/endpoints/flash/create.ts
index b46660d218..4fa65ac9aa 100644
--- a/packages/backend/src/server/api/endpoints/flash/create.ts
+++ b/packages/backend/src/server/api/endpoints/flash/create.ts
@@ -53,9 +53,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
) {
super(meta, paramDef, async (ps, me) => {
const flash = await this.flashsRepository.insert({
- id: this.idService.genId(),
+ id: this.idService.gen(),
userId: me.id,
- createdAt: new Date(),
updatedAt: new Date(),
title: ps.title,
summary: ps.summary,
diff --git a/packages/backend/src/server/api/endpoints/flash/like.ts b/packages/backend/src/server/api/endpoints/flash/like.ts
index a90e5f653a..1003249c0c 100644
--- a/packages/backend/src/server/api/endpoints/flash/like.ts
+++ b/packages/backend/src/server/api/endpoints/flash/like.ts
@@ -83,8 +83,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// Create like
await this.flashLikesRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
flashId: flash.id,
userId: me.id,
});
diff --git a/packages/backend/src/server/api/endpoints/following/create.ts b/packages/backend/src/server/api/endpoints/following/create.ts
index e0e7fed87a..9037944ef9 100644
--- a/packages/backend/src/server/api/endpoints/following/create.ts
+++ b/packages/backend/src/server/api/endpoints/following/create.ts
@@ -71,6 +71,7 @@ export const paramDef = {
type: 'object',
properties: {
userId: { type: 'string', format: 'misskey:id' },
+ withReplies: { type: 'boolean' }
},
required: ['userId'],
} as const;
@@ -112,7 +113,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
try {
- await this.userFollowingService.follow(follower, followee);
+ await this.userFollowingService.follow(follower, followee, { withReplies: ps.withReplies });
} catch (e) {
if (e instanceof IdentifiableError) {
if (e.id === '710e8fb0-b8c3-4922-be49-d5d93d8e6a6e') throw new ApiError(meta.errors.blocking);
diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts
index 94701712de..71e0ad4141 100644
--- a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts
@@ -76,8 +76,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
const post = await this.galleryPostsRepository.insert(new MiGalleryPost({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
updatedAt: new Date(),
title: ps.title,
description: ps.description,
diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts
index c557054066..561b2492ab 100644
--- a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts
@@ -83,8 +83,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// Create like
await this.galleryLikesRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
postId: post.id,
userId: me.id,
});
diff --git a/packages/backend/src/server/api/endpoints/hashtags/users.ts b/packages/backend/src/server/api/endpoints/hashtags/users.ts
index 1cef76d3d2..50aea79943 100644
--- a/packages/backend/src/server/api/endpoints/hashtags/users.ts
+++ b/packages/backend/src/server/api/endpoints/hashtags/users.ts
@@ -66,8 +66,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
switch (ps.sort) {
case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
- case '+createdAt': query.orderBy('user.createdAt', 'DESC'); break;
- case '-createdAt': query.orderBy('user.createdAt', 'ASC'); break;
+ case '+createdAt': query.orderBy('user.id', 'DESC'); break;
+ case '-createdAt': query.orderBy('user.id', 'ASC'); break;
case '+updatedAt': query.orderBy('user.updatedAt', 'DESC'); break;
case '-updatedAt': query.orderBy('user.updatedAt', 'ASC'); break;
}
diff --git a/packages/backend/src/server/api/endpoints/i/apps.ts b/packages/backend/src/server/api/endpoints/i/apps.ts
index daa3e536a4..09f6540a77 100644
--- a/packages/backend/src/server/api/endpoints/i/apps.ts
+++ b/packages/backend/src/server/api/endpoints/i/apps.ts
@@ -7,6 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { AccessTokensRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
+import { IdService } from '@/core/IdService.js';
export const meta = {
requireCredential: true,
@@ -27,6 +28,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
constructor(
@Inject(DI.accessTokensRepository)
private accessTokensRepository: AccessTokensRepository,
+
+ private idService: IdService,
) {
super(meta, paramDef, async (ps, me) => {
const query = this.accessTokensRepository.createQueryBuilder('token')
@@ -34,8 +37,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
.leftJoinAndSelect('token.app', 'app');
switch (ps.sort) {
- case '+createdAt': query.orderBy('token.createdAt', 'DESC'); break;
- case '-createdAt': query.orderBy('token.createdAt', 'ASC'); break;
+ case '+createdAt': query.orderBy('token.id', 'DESC'); break;
+ case '-createdAt': query.orderBy('token.id', 'ASC'); break;
case '+lastUsedAt': query.orderBy('token.lastUsedAt', 'DESC'); break;
case '-lastUsedAt': query.orderBy('token.lastUsedAt', 'ASC'); break;
default: query.orderBy('token.id', 'ASC'); break;
@@ -46,7 +49,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
return await Promise.all(tokens.map(token => ({
id: token.id,
name: token.name ?? token.app?.name,
- createdAt: token.createdAt,
+ createdAt: this.idService.parse(token.id).date.toISOString(),
lastUsedAt: token.lastUsedAt,
permission: token.permission,
})));
diff --git a/packages/backend/src/server/api/endpoints/i/import-following.ts b/packages/backend/src/server/api/endpoints/i/import-following.ts
index 38c9283043..e5fa2ac96a 100644
--- a/packages/backend/src/server/api/endpoints/i/import-following.ts
+++ b/packages/backend/src/server/api/endpoints/i/import-following.ts
@@ -52,6 +52,7 @@ export const paramDef = {
type: 'object',
properties: {
fileId: { type: 'string', format: 'misskey:id' },
+ withReplies: { type: 'boolean' },
},
required: ['fileId'],
} as const;
@@ -79,7 +80,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
);
if (checkMoving ? file.size > 32 * 1024 * 1024 : file.size > 64 * 1024) throw new ApiError(meta.errors.tooBigFile);
- this.queueService.createImportFollowingJob(me, file.id);
+ this.queueService.createImportFollowingJob(me, file.id, ps.withReplies);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/i/registry/set.ts b/packages/backend/src/server/api/endpoints/i/registry/set.ts
index c074b152df..6203e7aa8b 100644
--- a/packages/backend/src/server/api/endpoints/i/registry/set.ts
+++ b/packages/backend/src/server/api/endpoints/i/registry/set.ts
@@ -53,8 +53,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
});
} else {
await this.registryItemsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
updatedAt: new Date(),
userId: me.id,
domain: null,
diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts
index 48eaeff406..f00dba4a85 100644
--- a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts
+++ b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts
@@ -63,8 +63,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
const webhook = await this.webhooksRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
userId: me.id,
name: ps.name,
url: ps.url,
diff --git a/packages/backend/src/server/api/endpoints/invite/create.ts b/packages/backend/src/server/api/endpoints/invite/create.ts
index 7361ab616c..94836283fa 100644
--- a/packages/backend/src/server/api/endpoints/invite/create.ts
+++ b/packages/backend/src/server/api/endpoints/invite/create.ts
@@ -62,7 +62,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (policies.inviteLimit) {
const count = await this.registrationTicketsRepository.countBy({
- createdAt: MoreThan(new Date(Date.now() - (policies.inviteLimitCycle * 1000 * 60))),
+ id: MoreThan(this.idService.gen(Date.now() - (policies.inviteLimitCycle * 1000 * 60))),
createdById: me.id,
});
@@ -72,8 +72,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
const ticket = await this.registrationTicketsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
createdBy: me,
createdById: me.id,
expiresAt: policies.inviteExpirationTime ? new Date(Date.now() + (policies.inviteExpirationTime * 1000 * 60)) : null,
diff --git a/packages/backend/src/server/api/endpoints/invite/limit.ts b/packages/backend/src/server/api/endpoints/invite/limit.ts
index 43b94e4f06..1f4190c948 100644
--- a/packages/backend/src/server/api/endpoints/invite/limit.ts
+++ b/packages/backend/src/server/api/endpoints/invite/limit.ts
@@ -9,6 +9,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import type { RegistrationTicketsRepository } from '@/models/_.js';
import { RoleService } from '@/core/RoleService.js';
import { DI } from '@/di-symbols.js';
+import { IdService } from '@/core/IdService.js';
export const meta = {
tags: ['meta'],
@@ -41,12 +42,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private registrationTicketsRepository: RegistrationTicketsRepository,
private roleService: RoleService,
+ private idService: IdService,
) {
super(meta, paramDef, async (ps, me) => {
const policies = await this.roleService.getUserPolicies(me.id);
const count = policies.inviteLimit ? await this.registrationTicketsRepository.countBy({
- createdAt: MoreThan(new Date(Date.now() - (policies.inviteExpirationTime * 60 * 1000))),
+ id: MoreThan(this.idService.gen(Date.now() - (policies.inviteExpirationTime * 60 * 1000))),
createdById: me.id,
}) : null;
diff --git a/packages/backend/src/server/api/endpoints/miauth/gen-token.ts b/packages/backend/src/server/api/endpoints/miauth/gen-token.ts
index e40656cb6d..cac8f41f8e 100644
--- a/packages/backend/src/server/api/endpoints/miauth/gen-token.ts
+++ b/packages/backend/src/server/api/endpoints/miauth/gen-token.ts
@@ -59,8 +59,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// Insert access token doc
await this.accessTokensRepository.insert({
- id: this.idService.genId(),
- createdAt: now,
+ id: this.idService.gen(now.getTime()),
lastUsedAt: now,
session: ps.session,
userId: me.id,
diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts
index cc648e22a8..ed3dce7f35 100644
--- a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts
@@ -80,8 +80,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// Create favorite
await this.noteFavoritesRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
noteId: note.id,
userId: me.id,
});
diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts
index 8ac5f1b038..cbab13f30d 100644
--- a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts
@@ -5,7 +5,6 @@
import { Brackets } from 'typeorm';
import { Inject, Injectable } from '@nestjs/common';
-import * as Redis from 'ioredis';
import type { NotesRepository, FollowingsRepository, MiNote } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import ActiveUsersChart from '@/core/chart/charts/active-users.js';
@@ -15,7 +14,9 @@ import { RoleService } from '@/core/RoleService.js';
import { IdService } from '@/core/IdService.js';
import { isUserRelated } from '@/misc/is-user-related.js';
import { CacheService } from '@/core/CacheService.js';
-import { RedisTimelineService } from '@/core/RedisTimelineService.js';
+import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
+import { QueryService } from '@/core/QueryService.js';
+import { UserFollowingService } from '@/core/UserFollowingService.js';
import { ApiError } from '../../error.js';
export const meta = {
@@ -63,9 +64,6 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
- @Inject(DI.redisForTimelines)
- private redisForTimelines: Redis.Redis,
-
@Inject(DI.notesRepository)
private notesRepository: NotesRepository,
@@ -74,11 +72,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private activeUsersChart: ActiveUsersChart,
private idService: IdService,
private cacheService: CacheService,
- private redisTimelineService: RedisTimelineService,
+ private funoutTimelineService: FunoutTimelineService,
+ private queryService: QueryService,
+ private userFollowingService: UserFollowingService,
) {
super(meta, paramDef, async (ps, me) => {
- const untilId = ps.untilId ?? (ps.untilDate ? this.idService.genId(new Date(ps.untilDate!)) : null);
- const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.genId(new Date(ps.sinceDate!)) : null);
+ const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null);
+ const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null);
const policies = await this.roleService.getUserPolicies(me.id);
if (!policies.ltlAvailable) {
@@ -96,71 +96,152 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
]);
let noteIds: string[];
+ let shouldFallbackToDb = false;
if (ps.withFiles) {
- const [htlNoteIds, ltlNoteIds] = await this.redisTimelineService.getMulti([
+ const [htlNoteIds, ltlNoteIds] = await this.funoutTimelineService.getMulti([
`homeTimelineWithFiles:${me.id}`,
'localTimelineWithFiles',
], untilId, sinceId);
noteIds = Array.from(new Set([...htlNoteIds, ...ltlNoteIds]));
} else if (ps.withReplies) {
- const [htlNoteIds, ltlNoteIds, ltlReplyNoteIds] = await this.redisTimelineService.getMulti([
+ const [htlNoteIds, ltlNoteIds, ltlReplyNoteIds] = await this.funoutTimelineService.getMulti([
`homeTimeline:${me.id}`,
'localTimeline',
'localTimelineWithReplies',
], untilId, sinceId);
noteIds = Array.from(new Set([...htlNoteIds, ...ltlNoteIds, ...ltlReplyNoteIds]));
} else {
- const [htlNoteIds, ltlNoteIds] = await this.redisTimelineService.getMulti([
+ const [htlNoteIds, ltlNoteIds] = await this.funoutTimelineService.getMulti([
`homeTimeline:${me.id}`,
'localTimeline',
], untilId, sinceId);
noteIds = Array.from(new Set([...htlNoteIds, ...ltlNoteIds]));
+ shouldFallbackToDb = htlNoteIds.length === 0;
}
noteIds.sort((a, b) => a > b ? -1 : 1);
noteIds = noteIds.slice(0, ps.limit);
- if (noteIds.length === 0) {
- return [];
- }
+ shouldFallbackToDb = shouldFallbackToDb || (noteIds.length === 0);
+
+ if (!shouldFallbackToDb) {
+ const query = this.notesRepository.createQueryBuilder('note')
+ .where('note.id IN (:...noteIds)', { noteIds: noteIds })
+ .innerJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
+ .leftJoinAndSelect('note.channel', 'channel');
- const query = this.notesRepository.createQueryBuilder('note')
- .where('note.id IN (:...noteIds)', { noteIds: noteIds })
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser')
- .leftJoinAndSelect('note.channel', 'channel');
+ let timeline = await query.getMany();
- let timeline = await query.getMany();
+ timeline = timeline.filter(note => {
+ if (note.userId === me.id) {
+ return true;
+ }
+ if (isUserRelated(note, userIdsWhoBlockingMe)) return false;
+ if (isUserRelated(note, userIdsWhoMeMuting)) return false;
+ if (note.renoteId) {
+ if (note.text == null && note.fileIds.length === 0 && !note.hasPoll) {
+ if (isUserRelated(note, userIdsWhoMeMutingRenotes)) return false;
+ if (ps.withRenotes === false) return false;
+ }
+ }
- timeline = timeline.filter(note => {
- if (note.userId === me.id) {
return true;
+ });
+
+ // TODO: フィルタした結果件数が足りなかった場合の対応
+
+ timeline.sort((a, b) => a.id > b.id ? -1 : 1);
+
+ process.nextTick(() => {
+ this.activeUsersChart.read(me);
+ });
+
+ return await this.noteEntityService.packMany(timeline, me);
+ } else { // fallback to db
+ const followees = await this.userFollowingService.getFollowees(me.id);
+
+ const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
+ .andWhere(new Brackets(qb => {
+ if (followees.length > 0) {
+ const meOrFolloweeIds = [me.id, ...followees.map(f => f.followeeId)];
+ qb.where('note.userId IN (:...meOrFolloweeIds)', { meOrFolloweeIds: meOrFolloweeIds });
+ qb.orWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)');
+ } else {
+ qb.where('note.userId = :meId', { meId: me.id });
+ qb.orWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)');
+ }
+ }))
+ .innerJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
+
+ if (!ps.withReplies) {
+ query.andWhere(new Brackets(qb => {
+ qb
+ .where('note.replyId IS NULL') // 返信ではない
+ .orWhere(new Brackets(qb => {
+ qb // 返信だけど投稿者自身への返信
+ .where('note.replyId IS NOT NULL')
+ .andWhere('note.replyUserId = note.userId');
+ }));
+ }));
}
- if (isUserRelated(note, userIdsWhoBlockingMe)) return false;
- if (isUserRelated(note, userIdsWhoMeMuting)) return false;
- if (note.renoteId) {
- if (note.text == null && note.fileIds.length === 0 && !note.hasPoll) {
- if (isUserRelated(note, userIdsWhoMeMutingRenotes)) return false;
- if (ps.withRenotes === false) return false;
- }
+
+ this.queryService.generateVisibilityQuery(query, me);
+ this.queryService.generateMutedUserQuery(query, me);
+ this.queryService.generateBlockedUserQuery(query, me);
+ this.queryService.generateMutedUserRenotesQueryForNotes(query, me);
+
+ if (ps.includeMyRenotes === false) {
+ query.andWhere(new Brackets(qb => {
+ qb.orWhere('note.userId != :meId', { meId: me.id });
+ qb.orWhere('note.renoteId IS NULL');
+ qb.orWhere('note.text IS NOT NULL');
+ qb.orWhere('note.fileIds != \'{}\'');
+ qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
+ }));
}
- return true;
- });
+ if (ps.includeRenotedMyNotes === false) {
+ query.andWhere(new Brackets(qb => {
+ qb.orWhere('note.renoteUserId != :meId', { meId: me.id });
+ qb.orWhere('note.renoteId IS NULL');
+ qb.orWhere('note.text IS NOT NULL');
+ qb.orWhere('note.fileIds != \'{}\'');
+ qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
+ }));
+ }
- // TODO: フィルタした結果件数が足りなかった場合の対応
+ if (ps.includeLocalRenotes === false) {
+ query.andWhere(new Brackets(qb => {
+ qb.orWhere('note.renoteUserHost IS NOT NULL');
+ qb.orWhere('note.renoteId IS NULL');
+ qb.orWhere('note.text IS NOT NULL');
+ qb.orWhere('note.fileIds != \'{}\'');
+ qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
+ }));
+ }
+
+ if (ps.withFiles) {
+ query.andWhere('note.fileIds != \'{}\'');
+ }
+ //#endregion
- timeline.sort((a, b) => a.id > b.id ? -1 : 1);
+ const timeline = await query.limit(ps.limit).getMany();
- process.nextTick(() => {
- this.activeUsersChart.read(me);
- });
+ process.nextTick(() => {
+ this.activeUsersChart.read(me);
+ });
- return await this.noteEntityService.packMany(timeline, me);
+ return await this.noteEntityService.packMany(timeline, me);
+ }
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts
index d10c3bedbf..3b6c93fdf9 100644
--- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts
@@ -5,7 +5,6 @@
import { Brackets } from 'typeorm';
import { Inject, Injectable } from '@nestjs/common';
-import * as Redis from 'ioredis';
import type { MiNote, NotesRepository } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
@@ -15,7 +14,8 @@ import { RoleService } from '@/core/RoleService.js';
import { IdService } from '@/core/IdService.js';
import { CacheService } from '@/core/CacheService.js';
import { isUserRelated } from '@/misc/is-user-related.js';
-import { RedisTimelineService } from '@/core/RedisTimelineService.js';
+import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
+import { QueryService } from '@/core/QueryService.js';
import { ApiError } from '../../error.js';
export const meta = {
@@ -59,9 +59,6 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
- @Inject(DI.redisForTimelines)
- private redisForTimelines: Redis.Redis,
-
@Inject(DI.notesRepository)
private notesRepository: NotesRepository,
@@ -70,11 +67,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private activeUsersChart: ActiveUsersChart,
private idService: IdService,
private cacheService: CacheService,
- private redisTimelineService: RedisTimelineService,
+ private funoutTimelineService: FunoutTimelineService,
+ private queryService: QueryService,
) {
super(meta, paramDef, async (ps, me) => {
- const untilId = ps.untilId ?? (ps.untilDate ? this.idService.genId(new Date(ps.untilDate!)) : null);
- const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.genId(new Date(ps.sinceDate!)) : null);
+ const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null);
+ const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null);
const policies = await this.roleService.getUserPolicies(me ? me.id : null);
if (!policies.ltlAvailable) {
@@ -94,9 +92,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
let noteIds: string[];
if (ps.withFiles) {
- noteIds = await this.redisTimelineService.get('localTimelineWithFiles', untilId, sinceId);
+ noteIds = await this.funoutTimelineService.get('localTimelineWithFiles', untilId, sinceId);
} else {
- const [nonReplyNoteIds, replyNoteIds] = await this.redisTimelineService.getMulti([
+ const [nonReplyNoteIds, replyNoteIds] = await this.funoutTimelineService.getMulti([
'localTimeline',
'localTimelineWithReplies',
], untilId, sinceId);
@@ -106,49 +104,87 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
noteIds = noteIds.slice(0, ps.limit);
- if (noteIds.length === 0) {
- return [];
- }
+ if (noteIds.length > 0) {
+ const query = this.notesRepository.createQueryBuilder('note')
+ .where('note.id IN (:...noteIds)', { noteIds: noteIds })
+ .innerJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
+ .leftJoinAndSelect('note.channel', 'channel');
- const query = this.notesRepository.createQueryBuilder('note')
- .where('note.id IN (:...noteIds)', { noteIds: noteIds })
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser')
- .leftJoinAndSelect('note.channel', 'channel');
+ let timeline = await query.getMany();
- let timeline = await query.getMany();
+ timeline = timeline.filter(note => {
+ if (me && (note.userId === me.id)) {
+ return true;
+ }
+ if (!ps.withReplies && note.replyId && (me == null || note.replyUserId !== me.id)) return false;
+ if (me && isUserRelated(note, userIdsWhoBlockingMe)) return false;
+ if (me && isUserRelated(note, userIdsWhoMeMuting)) return false;
+ if (note.renoteId) {
+ if (note.text == null && note.fileIds.length === 0 && !note.hasPoll) {
+ if (me && isUserRelated(note, userIdsWhoMeMutingRenotes)) return false;
+ if (ps.withRenotes === false) return false;
+ }
+ }
- timeline = timeline.filter(note => {
- if (me && (note.userId === me.id)) {
return true;
- }
- if (!ps.withReplies && note.replyId && (me == null || note.replyUserId !== me.id)) return false;
- if (me && isUserRelated(note, userIdsWhoBlockingMe)) return false;
- if (me && isUserRelated(note, userIdsWhoMeMuting)) return false;
- if (note.renoteId) {
- if (note.text == null && note.fileIds.length === 0 && !note.hasPoll) {
- if (me && isUserRelated(note, userIdsWhoMeMutingRenotes)) return false;
- if (ps.withRenotes === false) return false;
+ });
+
+ // TODO: フィルタした結果件数が足りなかった場合の対応
+
+ timeline.sort((a, b) => a.id > b.id ? -1 : 1);
+
+ process.nextTick(() => {
+ if (me) {
+ this.activeUsersChart.read(me);
}
- }
+ });
- return true;
- });
+ return await this.noteEntityService.packMany(timeline, me);
+ } else { // fallback to db
+ const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'),
+ ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
+ .andWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)')
+ .innerJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
- // TODO: フィルタした結果件数が足りなかった場合の対応
+ this.queryService.generateVisibilityQuery(query, me);
+ if (me) this.queryService.generateMutedUserQuery(query, me);
+ if (me) this.queryService.generateBlockedUserQuery(query, me);
+ if (me) this.queryService.generateMutedUserRenotesQueryForNotes(query, me);
- timeline.sort((a, b) => a.id > b.id ? -1 : 1);
+ if (ps.withFiles) {
+ query.andWhere('note.fileIds != \'{}\'');
+ }
- process.nextTick(() => {
- if (me) {
- this.activeUsersChart.read(me);
+ if (!ps.withReplies) {
+ query.andWhere(new Brackets(qb => {
+ qb
+ .where('note.replyId IS NULL') // 返信ではない
+ .orWhere(new Brackets(qb => {
+ qb // 返信だけど投稿者自身への返信
+ .where('note.replyId IS NOT NULL')
+ .andWhere('note.replyUserId = note.userId');
+ }));
+ }));
}
- });
- return await this.noteEntityService.packMany(timeline, me);
+ const timeline = await query.limit(ps.limit).getMany();
+
+ process.nextTick(() => {
+ if (me) {
+ this.activeUsersChart.read(me);
+ }
+ });
+
+ return await this.noteEntityService.packMany(timeline, me);
+ }
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts b/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts
index 986201e950..af7ff8bdcd 100644
--- a/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts
+++ b/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts
@@ -98,7 +98,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
id: In(polls.map(poll => poll.noteId)),
},
order: {
- createdAt: 'DESC',
+ id: 'DESC',
},
});
diff --git a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts
index a58bf09b85..734c3f0e63 100644
--- a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts
+++ b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts
@@ -145,8 +145,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// Create vote
const vote = await this.pollVotesRepository.insert({
- id: this.idService.genId(),
- createdAt,
+ id: this.idService.gen(createdAt.getTime()),
noteId: note.id,
userId: me.id,
choice: ps.choice,
diff --git a/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts b/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts
index 449a838604..b2cdaa00ac 100644
--- a/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts
@@ -72,8 +72,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
await this.noteReadService.read(me.id, mutedNotes);
await this.noteThreadMutingsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
threadId: note.threadId ?? note.id,
userId: me.id,
});
diff --git a/packages/backend/src/server/api/endpoints/notes/timeline.ts b/packages/backend/src/server/api/endpoints/notes/timeline.ts
index 760d52c9db..3b597107ae 100644
--- a/packages/backend/src/server/api/endpoints/notes/timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/timeline.ts
@@ -5,8 +5,7 @@
import { Brackets } from 'typeorm';
import { Inject, Injectable } from '@nestjs/common';
-import * as Redis from 'ioredis';
-import type { NotesRepository, FollowingsRepository, MiNote } from '@/models/_.js';
+import type { NotesRepository } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { QueryService } from '@/core/QueryService.js';
import ActiveUsersChart from '@/core/chart/charts/active-users.js';
@@ -15,7 +14,8 @@ import { DI } from '@/di-symbols.js';
import { IdService } from '@/core/IdService.js';
import { CacheService } from '@/core/CacheService.js';
import { isUserRelated } from '@/misc/is-user-related.js';
-import { RedisTimelineService } from '@/core/RedisTimelineService.js';
+import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
+import { UserFollowingService } from '@/core/UserFollowingService.js';
export const meta = {
tags: ['notes'],
@@ -53,9 +53,6 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
- @Inject(DI.redisForTimelines)
- private redisForTimelines: Redis.Redis,
-
@Inject(DI.notesRepository)
private notesRepository: NotesRepository,
@@ -63,11 +60,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private activeUsersChart: ActiveUsersChart,
private idService: IdService,
private cacheService: CacheService,
- private redisTimelineService: RedisTimelineService,
+ private funoutTimelineService: FunoutTimelineService,
+ private userFollowingService: UserFollowingService,
+ private queryService: QueryService,
) {
super(meta, paramDef, async (ps, me) => {
- const untilId = ps.untilId ?? (ps.untilDate ? this.idService.genId(new Date(ps.untilDate!)) : null);
- const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.genId(new Date(ps.sinceDate!)) : null);
+ const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null);
+ const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null);
const [
followings,
@@ -81,52 +80,127 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
this.cacheService.userBlockedCache.fetch(me.id),
]);
- let noteIds = await this.redisTimelineService.get(ps.withFiles ? `homeTimelineWithFiles:${me.id}` : `homeTimeline:${me.id}`, untilId, sinceId);
+ let noteIds = await this.funoutTimelineService.get(ps.withFiles ? `homeTimelineWithFiles:${me.id}` : `homeTimeline:${me.id}`, untilId, sinceId);
noteIds = noteIds.slice(0, ps.limit);
- if (noteIds.length === 0) {
- return [];
- }
+ if (noteIds.length > 0) {
+ const query = this.notesRepository.createQueryBuilder('note')
+ .where('note.id IN (:...noteIds)', { noteIds: noteIds })
+ .innerJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
+ .leftJoinAndSelect('note.channel', 'channel');
- const query = this.notesRepository.createQueryBuilder('note')
- .where('note.id IN (:...noteIds)', { noteIds: noteIds })
- .innerJoinAndSelect('note.user', 'user')
- .leftJoinAndSelect('note.reply', 'reply')
- .leftJoinAndSelect('note.renote', 'renote')
- .leftJoinAndSelect('reply.user', 'replyUser')
- .leftJoinAndSelect('renote.user', 'renoteUser')
- .leftJoinAndSelect('note.channel', 'channel');
+ let timeline = await query.getMany();
- let timeline = await query.getMany();
+ timeline = timeline.filter(note => {
+ if (note.userId === me.id) {
+ return true;
+ }
+ if (isUserRelated(note, userIdsWhoBlockingMe)) return false;
+ if (isUserRelated(note, userIdsWhoMeMuting)) return false;
+ if (note.renoteId) {
+ if (note.text == null && note.fileIds.length === 0 && !note.hasPoll) {
+ if (isUserRelated(note, userIdsWhoMeMutingRenotes)) return false;
+ if (ps.withRenotes === false) return false;
+ }
+ }
+ if (note.reply && note.reply.visibility === 'followers') {
+ if (!Object.hasOwn(followings, note.reply.userId)) return false;
+ }
- timeline = timeline.filter(note => {
- if (note.userId === me.id) {
return true;
+ });
+
+ // TODO: フィルタした結果件数が足りなかった場合の対応
+
+ timeline.sort((a, b) => a.id > b.id ? -1 : 1);
+
+ process.nextTick(() => {
+ this.activeUsersChart.read(me);
+ });
+
+ return await this.noteEntityService.packMany(timeline, me);
+ } else { // fallback to db
+ const followees = await this.userFollowingService.getFollowees(me.id);
+
+ //#region Construct query
+ const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
+ .andWhere('note.channelId IS NULL')
+ .innerJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
+
+ if (followees.length > 0) {
+ const meOrFolloweeIds = [me.id, ...followees.map(f => f.followeeId)];
+
+ query.andWhere('note.userId IN (:...meOrFolloweeIds)', { meOrFolloweeIds: meOrFolloweeIds });
+ } else {
+ query.andWhere('note.userId = :meId', { meId: me.id });
}
- if (isUserRelated(note, userIdsWhoBlockingMe)) return false;
- if (isUserRelated(note, userIdsWhoMeMuting)) return false;
- if (note.renoteId) {
- if (note.text == null && note.fileIds.length === 0 && !note.hasPoll) {
- if (isUserRelated(note, userIdsWhoMeMutingRenotes)) return false;
- if (ps.withRenotes === false) return false;
- }
+
+ query.andWhere(new Brackets(qb => {
+ qb
+ .where('note.replyId IS NULL') // 返信ではない
+ .orWhere(new Brackets(qb => {
+ qb // 返信だけど投稿者自身への返信
+ .where('note.replyId IS NOT NULL')
+ .andWhere('note.replyUserId = note.userId');
+ }));
+ }));
+
+ this.queryService.generateVisibilityQuery(query, me);
+ this.queryService.generateMutedUserQuery(query, me);
+ this.queryService.generateBlockedUserQuery(query, me);
+ this.queryService.generateMutedUserRenotesQueryForNotes(query, me);
+
+ if (ps.includeMyRenotes === false) {
+ query.andWhere(new Brackets(qb => {
+ qb.orWhere('note.userId != :meId', { meId: me.id });
+ qb.orWhere('note.renoteId IS NULL');
+ qb.orWhere('note.text IS NOT NULL');
+ qb.orWhere('note.fileIds != \'{}\'');
+ qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
+ }));
}
- if (note.reply && note.reply.visibility === 'followers') {
- if (!Object.hasOwn(followings, note.reply.userId)) return false;
+
+ if (ps.includeRenotedMyNotes === false) {
+ query.andWhere(new Brackets(qb => {
+ qb.orWhere('note.renoteUserId != :meId', { meId: me.id });
+ qb.orWhere('note.renoteId IS NULL');
+ qb.orWhere('note.text IS NOT NULL');
+ qb.orWhere('note.fileIds != \'{}\'');
+ qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
+ }));
}
- return true;
- });
+ if (ps.includeLocalRenotes === false) {
+ query.andWhere(new Brackets(qb => {
+ qb.orWhere('note.renoteUserHost IS NOT NULL');
+ qb.orWhere('note.renoteId IS NULL');
+ qb.orWhere('note.text IS NOT NULL');
+ qb.orWhere('note.fileIds != \'{}\'');
+ qb.orWhere('0 < (SELECT COUNT(*) FROM poll WHERE poll."noteId" = note.id)');
+ }));
+ }
- // TODO: フィルタした結果件数が足りなかった場合の対応
+ if (ps.withFiles) {
+ query.andWhere('note.fileIds != \'{}\'');
+ }
+ //#endregion
- timeline.sort((a, b) => a.id > b.id ? -1 : 1);
+ const timeline = await query.limit(ps.limit).getMany();
- process.nextTick(() => {
- this.activeUsersChart.read(me);
- });
+ process.nextTick(() => {
+ this.activeUsersChart.read(me);
+ });
- return await this.noteEntityService.packMany(timeline, me);
+ return await this.noteEntityService.packMany(timeline, me);
+ }
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
index f7ee58264e..96e1e94f7c 100644
--- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -3,19 +3,16 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Brackets } from 'typeorm';
import { Inject, Injectable } from '@nestjs/common';
-import * as Redis from 'ioredis';
-import type { NotesRepository, UserListsRepository, UserListMembershipsRepository, MiNote } from '@/models/_.js';
+import type { NotesRepository, UserListsRepository } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import { QueryService } from '@/core/QueryService.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import ActiveUsersChart from '@/core/chart/charts/active-users.js';
import { DI } from '@/di-symbols.js';
import { CacheService } from '@/core/CacheService.js';
import { IdService } from '@/core/IdService.js';
import { isUserRelated } from '@/misc/is-user-related.js';
-import { RedisTimelineService } from '@/core/RedisTimelineService.js';
+import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
import { ApiError } from '../../error.js';
export const meta = {
@@ -67,9 +64,6 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
- @Inject(DI.redisForTimelines)
- private redisForTimelines: Redis.Redis,
-
@Inject(DI.notesRepository)
private notesRepository: NotesRepository,
@@ -80,11 +74,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private activeUsersChart: ActiveUsersChart,
private cacheService: CacheService,
private idService: IdService,
- private redisTimelineService: RedisTimelineService,
+ private funoutTimelineService: FunoutTimelineService,
) {
super(meta, paramDef, async (ps, me) => {
- const untilId = ps.untilId ?? (ps.untilDate ? this.idService.genId(new Date(ps.untilDate!)) : null);
- const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.genId(new Date(ps.sinceDate!)) : null);
+ const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null);
+ const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null);
const list = await this.userListsRepository.findOneBy({
id: ps.listId,
@@ -105,7 +99,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
this.cacheService.userBlockedCache.fetch(me.id),
]);
- let noteIds = await this.redisTimelineService.get(ps.withFiles ? `userListTimelineWithFiles:${list.id}` : `userListTimeline:${list.id}`, untilId, sinceId);
+ let noteIds = await this.funoutTimelineService.get(ps.withFiles ? `userListTimelineWithFiles:${list.id}` : `userListTimeline:${list.id}`, untilId, sinceId);
noteIds = noteIds.slice(0, ps.limit);
if (noteIds.length === 0) {
diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts
index c0e8fab16c..4c2ef516e5 100644
--- a/packages/backend/src/server/api/endpoints/pages/create.ts
+++ b/packages/backend/src/server/api/endpoints/pages/create.ts
@@ -103,8 +103,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
});
const page = await this.pagesRepository.insert(new MiPage({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
updatedAt: new Date(),
title: ps.title,
name: ps.name,
diff --git a/packages/backend/src/server/api/endpoints/pages/like.ts b/packages/backend/src/server/api/endpoints/pages/like.ts
index 6c69cad9d5..8c18982b50 100644
--- a/packages/backend/src/server/api/endpoints/pages/like.ts
+++ b/packages/backend/src/server/api/endpoints/pages/like.ts
@@ -83,8 +83,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// Create like
await this.pageLikesRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
pageId: page.id,
userId: me.id,
});
diff --git a/packages/backend/src/server/api/endpoints/promo/read.ts b/packages/backend/src/server/api/endpoints/promo/read.ts
index b197756acc..7d07c92178 100644
--- a/packages/backend/src/server/api/endpoints/promo/read.ts
+++ b/packages/backend/src/server/api/endpoints/promo/read.ts
@@ -60,8 +60,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
await this.promoReadsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
noteId: note.id,
userId: me.id,
});
diff --git a/packages/backend/src/server/api/endpoints/renote-mute/create.ts b/packages/backend/src/server/api/endpoints/renote-mute/create.ts
index 3c9d266e21..7ff7b5de3a 100644
--- a/packages/backend/src/server/api/endpoints/renote-mute/create.ts
+++ b/packages/backend/src/server/api/endpoints/renote-mute/create.ts
@@ -90,8 +90,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// Create mute
await this.renoteMutingsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
muterId: muter.id,
muteeId: mutee.id,
} as MiRenoteMuting);
diff --git a/packages/backend/src/server/api/endpoints/request-reset-password.ts b/packages/backend/src/server/api/endpoints/request-reset-password.ts
index adb160c58b..f13710e1dd 100644
--- a/packages/backend/src/server/api/endpoints/request-reset-password.ts
+++ b/packages/backend/src/server/api/endpoints/request-reset-password.ts
@@ -84,8 +84,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const token = secureRndstr(64, { chars: L_CHARS });
await this.passwordResetRequestsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
userId: profile.userId,
token,
});
diff --git a/packages/backend/src/server/api/endpoints/reset-password.ts b/packages/backend/src/server/api/endpoints/reset-password.ts
index 1858c922a0..3a6dc14bcd 100644
--- a/packages/backend/src/server/api/endpoints/reset-password.ts
+++ b/packages/backend/src/server/api/endpoints/reset-password.ts
@@ -8,6 +8,7 @@ import { Inject, Injectable } from '@nestjs/common';
import type { UserProfilesRepository, PasswordResetRequestsRepository } from '@/models/_.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { DI } from '@/di-symbols.js';
+import { IdService } from '@/core/IdService.js';
export const meta = {
tags: ['reset password'],
@@ -38,6 +39,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject(DI.userProfilesRepository)
private userProfilesRepository: UserProfilesRepository,
+
+ private idService: IdService,
) {
super(meta, paramDef, async (ps, me) => {
const req = await this.passwordResetRequestsRepository.findOneByOrFail({
@@ -45,7 +48,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
});
// 発行してから30分以上経過していたら無効
- if (Date.now() - req.createdAt.getTime() > 1000 * 60 * 30) {
+ if (Date.now() - this.idService.parse(req.id).date.getTime() > 1000 * 60 * 30) {
throw new Error(); // TODO
}
diff --git a/packages/backend/src/server/api/endpoints/roles/notes.ts b/packages/backend/src/server/api/endpoints/roles/notes.ts
index 0db51abc55..daa9affc20 100644
--- a/packages/backend/src/server/api/endpoints/roles/notes.ts
+++ b/packages/backend/src/server/api/endpoints/roles/notes.ts
@@ -11,7 +11,7 @@ import { QueryService } from '@/core/QueryService.js';
import { DI } from '@/di-symbols.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { IdService } from '@/core/IdService.js';
-import { RedisTimelineService } from '@/core/RedisTimelineService.js';
+import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
import { ApiError } from '../../error.js';
export const meta = {
@@ -66,11 +66,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private idService: IdService,
private noteEntityService: NoteEntityService,
private queryService: QueryService,
- private redisTimelineService: RedisTimelineService,
+ private funoutTimelineService: FunoutTimelineService,
) {
super(meta, paramDef, async (ps, me) => {
- const untilId = ps.untilId ?? (ps.untilDate ? this.idService.genId(new Date(ps.untilDate!)) : null);
- const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.genId(new Date(ps.sinceDate!)) : null);
+ const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null);
+ const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null);
const role = await this.rolesRepository.findOneBy({
id: ps.roleId,
@@ -84,7 +84,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
return [];
}
- let noteIds = await this.redisTimelineService.get(`roleTimeline:${role.id}`, untilId, sinceId);
+ let noteIds = await this.funoutTimelineService.get(`roleTimeline:${role.id}`, untilId, sinceId);
noteIds = noteIds.slice(0, ps.limit);
if (noteIds.length === 0) {
diff --git a/packages/backend/src/server/api/endpoints/sw/register.ts b/packages/backend/src/server/api/endpoints/sw/register.ts
index 5cfbeab73f..9ab062326d 100644
--- a/packages/backend/src/server/api/endpoints/sw/register.ts
+++ b/packages/backend/src/server/api/endpoints/sw/register.ts
@@ -88,8 +88,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
await this.swSubscriptionsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
userId: me.id,
endpoint: ps.endpoint,
auth: ps.auth,
diff --git a/packages/backend/src/server/api/endpoints/users.ts b/packages/backend/src/server/api/endpoints/users.ts
index 21c585f1ad..8dc5841314 100644
--- a/packages/backend/src/server/api/endpoints/users.ts
+++ b/packages/backend/src/server/api/endpoints/users.ts
@@ -74,8 +74,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
switch (ps.sort) {
case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
- case '+createdAt': query.orderBy('user.createdAt', 'DESC'); break;
- case '-createdAt': query.orderBy('user.createdAt', 'ASC'); break;
+ case '+createdAt': query.orderBy('user.id', 'DESC'); break;
+ case '-createdAt': query.orderBy('user.id', 'ASC'); break;
case '+updatedAt': query.andWhere('user.updatedAt IS NOT NULL').orderBy('user.updatedAt', 'DESC'); break;
case '-updatedAt': query.andWhere('user.updatedAt IS NOT NULL').orderBy('user.updatedAt', 'ASC'); break;
default: query.orderBy('user.id', 'ASC'); break;
diff --git a/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts b/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts
index f2f6c4303a..4eb37c3e43 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts
@@ -104,8 +104,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
const userList = await this.userListsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
userId: me.id,
name: ps.name,
} as MiUserList).then(x => this.userListsRepository.findOneByOrFail(x.identifiers[0]));
diff --git a/packages/backend/src/server/api/endpoints/users/lists/create.ts b/packages/backend/src/server/api/endpoints/users/lists/create.ts
index 60b2b3f17e..e86e4c0ded 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/create.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/create.ts
@@ -66,8 +66,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
const userList = await this.userListsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
userId: me.id,
name: ps.name,
} as MiUserList).then(x => this.userListsRepository.findOneByOrFail(x.identifiers[0]));
diff --git a/packages/backend/src/server/api/endpoints/users/lists/favorite.ts b/packages/backend/src/server/api/endpoints/users/lists/favorite.ts
index 1707afee60..2ecf0a1256 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/favorite.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/favorite.ts
@@ -69,8 +69,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
}
await this.userListFavoritesRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
userId: me.id,
userListId: ps.listId,
});
diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts
index df0951ce74..343d320f6e 100644
--- a/packages/backend/src/server/api/endpoints/users/notes.ts
+++ b/packages/backend/src/server/api/endpoints/users/notes.ts
@@ -14,7 +14,7 @@ import { CacheService } from '@/core/CacheService.js';
import { IdService } from '@/core/IdService.js';
import { isUserRelated } from '@/misc/is-user-related.js';
import { QueryService } from '@/core/QueryService.js';
-import { RedisTimelineService } from '@/core/RedisTimelineService.js';
+import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
import { ApiError } from '../../error.js';
export const meta = {
@@ -71,11 +71,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private queryService: QueryService,
private cacheService: CacheService,
private idService: IdService,
- private redisTimelineService: RedisTimelineService,
+ private funoutTimelineService: FunoutTimelineService,
) {
super(meta, paramDef, async (ps, me) => {
- const untilId = ps.untilId ?? (ps.untilDate ? this.idService.genId(new Date(ps.untilDate!)) : null);
- const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.genId(new Date(ps.sinceDate!)) : null);
+ const untilId = ps.untilId ?? (ps.untilDate ? this.idService.gen(ps.untilDate!) : null);
+ const sinceId = ps.sinceId ?? (ps.sinceDate ? this.idService.gen(ps.sinceDate!) : null);
const isRangeSpecified = untilId != null && sinceId != null;
const isSelf = me && (me.id === ps.userId);
@@ -87,9 +87,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
]) : [new Set<string>()];
const [noteIdsRes, repliesNoteIdsRes, channelNoteIdsRes] = await Promise.all([
- this.redisTimelineService.get(ps.withFiles ? `userTimelineWithFiles:${ps.userId}` : `userTimeline:${ps.userId}`, untilId, sinceId),
- ps.withReplies ? this.redisTimelineService.get(`userTimelineWithReplies:${ps.userId}`, untilId, sinceId) : Promise.resolve([]),
- ps.withChannelNotes ? this.redisTimelineService.get(`userTimelineWithChannel:${ps.userId}`, untilId, sinceId) : Promise.resolve([]),
+ this.funoutTimelineService.get(ps.withFiles ? `userTimelineWithFiles:${ps.userId}` : `userTimeline:${ps.userId}`, untilId, sinceId),
+ ps.withReplies ? this.funoutTimelineService.get(`userTimelineWithReplies:${ps.userId}`, untilId, sinceId) : Promise.resolve([]),
+ ps.withChannelNotes ? this.funoutTimelineService.get(`userTimelineWithChannel:${ps.userId}`, untilId, sinceId) : Promise.resolve([]),
]);
let noteIds = Array.from(new Set([
@@ -151,7 +151,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
.leftJoinAndSelect('renote.user', 'renoteUser');
if (ps.withChannelNotes) {
- if (!isSelf) query.andWhere('channel.isSensitive = false');
+ if (!isSelf) query.andWhere(new Brackets(qb => {
+ qb.orWhere('note.channelId IS NULL');
+ qb.orWhere('channel.isSensitive = false');
+ }));
} else {
query.andWhere('note.channelId IS NULL');
}
diff --git a/packages/backend/src/server/api/endpoints/users/report-abuse.ts b/packages/backend/src/server/api/endpoints/users/report-abuse.ts
index 50aa6fa09e..3bcf44cc42 100644
--- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts
+++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts
@@ -82,8 +82,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
const report = await this.abuseUserReportsRepository.insert({
- id: this.idService.genId(),
- createdAt: new Date(),
+ id: this.idService.gen(),
targetUserId: user.id,
targetUserHost: user.host,
reporterId: me.id,
diff --git a/packages/backend/src/server/api/endpoints/users/update-memo.ts b/packages/backend/src/server/api/endpoints/users/update-memo.ts
index 194d488052..b3f67815ef 100644
--- a/packages/backend/src/server/api/endpoints/users/update-memo.ts
+++ b/packages/backend/src/server/api/endpoints/users/update-memo.ts
@@ -72,7 +72,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (!previousMemo) {
await this.userMemosRepository.insert({
- id: this.idService.genId(),
+ id: this.idService.gen(),
userId: me.id,
targetUserId: target.id,
memo: ps.memo,