dbに保存するようにした

Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
This commit is contained in:
mattyatea 2023-11-08 15:33:46 +09:00
parent e133a6b6a4
commit 387faf55cf
No known key found for this signature in database
GPG Key ID: 068E54E2C33BEF9A
8 changed files with 160 additions and 42 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "misskey", "name": "misskey",
"version": "2023.11.0", "version": "2023.11.2",
"codename": "nasubi", "codename": "nasubi",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -0,0 +1,11 @@
export class Schedulenote1699337454434 {
name = 'Schedulenote1699337454434'
async up(queryRunner) {
await queryRunner.query(`CREATE TABLE "note_schedule" ("id" character varying(32) NOT NULL, "note" jsonb NOT NULL, "userId" character varying(260) NOT NULL, CONSTRAINT "PK_3a1ae2db41988f4994268218436" PRIMARY KEY ("id"))`);
}
async down(queryRunner) {
await queryRunner.query(`DROP TABLE "note_schedule"`);
}
}

View File

@ -14,16 +14,13 @@ import type { MiDriveFile } from './DriveFile.js';
@Entity('note_schedule') @Entity('note_schedule')
export class MiNoteSchedule { export class MiNoteSchedule {
@PrimaryColumn(id()) @PrimaryColumn(id())
public noteId: MiNote['id']; public id: string;
@Column('string') @Column('jsonb')
public note:{ apEmojis: any[] | undefined; visibility: any; apMentions: any[] | undefined; visibleUsers: MiUser[]; channel: null | MiChannel; poll: { multiple: any; choices: any; expiresAt: Date | null } | undefined; renote: null | MiNote; localOnly: any; cw: any; apHashtags: any[] | undefined; reactionAcceptance: any; files: MiDriveFile[]; text: any; reply: null | MiNote }; public note:{createdAt?: Date | undefined ; apEmojis: any[] | undefined; visibility: any; apMentions: any[] | undefined; visibleUsers: MiUser[]; channel: null | MiChannel; poll: { multiple: any; choices: any; expiresAt: Date | null } | undefined; renote: null | MiNote; localOnly: any; cw: any; apHashtags: any[] | undefined; reactionAcceptance: any; files: MiDriveFile[]; text: any; reply: null | MiNote };
@Column('string') @Column('varchar', {
public user: MiUser & {host: null;uri: null;}; length: 260,
@Column('timestamp with time zone', {
nullable: true,
}) })
public expiresAt: Date; public userId: MiUser['id'];
} }

View File

@ -5,7 +5,74 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { MiAbuseUserReport, MiAccessToken, MiAd, MiAnnouncement, MiAnnouncementRead, MiAntenna, MiApp, MiAuthSession, MiAvatarDecoration, MiBlocking, MiChannel, MiChannelFavorite, MiChannelFollowing, MiClip, MiClipFavorite, MiClipNote, MiDriveFile, MiDriveFolder, MiEmoji, MiFlash, MiFlashLike, MiFollowRequest, MiFollowing, MiGalleryLike, MiGalleryPost, MiHashtag, MiInstance, MiMeta, MiModerationLog, MiMuting, MiNote, MiNoteFavorite, MiNoteReaction, MiNoteThreadMuting, MiNoteUnread, MiPage, MiPageLike, MiPasswordResetRequest, MiPoll, MiPollVote, MiPromoNote, MiPromoRead, MiRegistrationTicket, MiRegistryItem, MiRelay, MiRenoteMuting, MiRetentionAggregation, MiRole, MiRoleAssignment, MiSignin, MiSwSubscription, MiUsedUsername, MiUser, MiUserIp, MiUserKeypair, MiUserList, MiUserListFavorite, MiUserListMembership, MiUserMemo, MiUserNotePining, MiUserPending, MiUserProfile, MiUserPublickey, MiUserSecurityKey, MiWebhook } from './_.js'; import {
MiAbuseUserReport,
MiAccessToken,
MiAd,
MiAnnouncement,
MiAnnouncementRead,
MiAntenna,
MiApp,
MiAuthSession,
MiAvatarDecoration,
MiBlocking,
MiChannel,
MiChannelFavorite,
MiChannelFollowing,
MiClip,
MiClipFavorite,
MiClipNote,
MiDriveFile,
MiDriveFolder,
MiEmoji,
MiFlash,
MiFlashLike,
MiFollowRequest,
MiFollowing,
MiGalleryLike,
MiGalleryPost,
MiHashtag,
MiInstance,
MiMeta,
MiModerationLog,
MiMuting,
MiNote,
MiNoteFavorite,
MiNoteReaction,
MiNoteThreadMuting,
MiNoteUnread,
MiPage,
MiPageLike,
MiPasswordResetRequest,
MiPoll,
MiPollVote,
MiPromoNote,
MiPromoRead,
MiRegistrationTicket,
MiRegistryItem,
MiRelay,
MiRenoteMuting,
MiRetentionAggregation,
MiRole,
MiRoleAssignment,
MiSignin,
MiSwSubscription,
MiUsedUsername,
MiUser,
MiUserIp,
MiUserKeypair,
MiUserList,
MiUserListFavorite,
MiUserListMembership,
MiUserMemo,
MiUserNotePining,
MiUserPending,
MiUserProfile,
MiUserPublickey,
MiUserSecurityKey,
MiWebhook,
MiNoteSchedule,
} from './_.js';
import type { DataSource } from 'typeorm'; import type { DataSource } from 'typeorm';
import type { Provider } from '@nestjs/common'; import type { Provider } from '@nestjs/common';
@ -21,6 +88,12 @@ const $notesRepository: Provider = {
inject: [DI.db], inject: [DI.db],
}; };
const $noteScheduleRepository: Provider = {
provide: DI.noteScheduleRepository,
useFactory: (db: DataSource) => db.getRepository(MiNoteSchedule),
inject: [DI.db],
};
const $announcementsRepository: Provider = { const $announcementsRepository: Provider = {
provide: DI.announcementsRepository, provide: DI.announcementsRepository,
useFactory: (db: DataSource) => db.getRepository(MiAnnouncement), useFactory: (db: DataSource) => db.getRepository(MiAnnouncement),
@ -405,6 +478,7 @@ const $userMemosRepository: Provider = {
providers: [ providers: [
$usersRepository, $usersRepository,
$notesRepository, $notesRepository,
$noteScheduleRepository,
$announcementsRepository, $announcementsRepository,
$announcementReadsRepository, $announcementReadsRepository,
$appsRepository, $appsRepository,
@ -472,6 +546,7 @@ const $userMemosRepository: Provider = {
exports: [ exports: [
$usersRepository, $usersRepository,
$notesRepository, $notesRepository,
$noteScheduleRepository,
$announcementsRepository, $announcementsRepository,
$announcementReadsRepository, $announcementReadsRepository,
$appsRepository, $appsRepository,

View File

@ -76,6 +76,7 @@ import { MiRoleAssignment } from '@/models/RoleAssignment.js';
import { MiFlash } from '@/models/Flash.js'; import { MiFlash } from '@/models/Flash.js';
import { MiFlashLike } from '@/models/FlashLike.js'; import { MiFlashLike } from '@/models/FlashLike.js';
import { MiUserMemo } from '@/models/UserMemo.js'; import { MiUserMemo } from '@/models/UserMemo.js';
import { MiNoteSchedule } from '@/models/NoteSchedule.js';
import { Config } from '@/config.js'; import { Config } from '@/config.js';
import MisskeyLogger from '@/logger.js'; import MisskeyLogger from '@/logger.js';
@ -149,6 +150,7 @@ export const entities = [
MiRenoteMuting, MiRenoteMuting,
MiBlocking, MiBlocking,
MiNote, MiNote,
MiNoteSchedule,
MiNoteFavorite, MiNoteFavorite,
MiNoteReaction, MiNoteReaction,
MiNoteThreadMuting, MiNoteThreadMuting,

View File

@ -7,6 +7,8 @@ import { Inject, Injectable } from '@nestjs/common';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { NoteCreateService } from '@/core/NoteCreateService.js'; import { NoteCreateService } from '@/core/NoteCreateService.js';
import type { NoteScheduleRepository, UsersRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
import { QueueLoggerService } from '../QueueLoggerService.js'; import { QueueLoggerService } from '../QueueLoggerService.js';
import type * as Bull from 'bullmq'; import type * as Bull from 'bullmq';
import type { ScheduleNotePostJobData } from '../types.js'; import type { ScheduleNotePostJobData } from '../types.js';
@ -16,6 +18,12 @@ export class ScheduleNotePostProcessorService {
private logger: Logger; private logger: Logger;
constructor( constructor(
@Inject(DI.noteScheduleRepository)
private noteScheduleRepository: NoteScheduleRepository,
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
private noteCreateService: NoteCreateService, private noteCreateService: NoteCreateService,
private queueLoggerService: QueueLoggerService, private queueLoggerService: QueueLoggerService,
) { ) {
@ -24,7 +32,15 @@ export class ScheduleNotePostProcessorService {
@bindThis @bindThis
public async process(job: Bull.Job<ScheduleNotePostJobData>): Promise<void> { public async process(job: Bull.Job<ScheduleNotePostJobData>): Promise<void> {
job.data.note.createdAt = new Date(); this.noteScheduleRepository.findOneBy({ id: job.data.scheduleNoteId }).then(async (data) => {
await this.noteCreateService.create(job.data.user, job.data.note); if (!data) {
this.logger.warn(`Schedule note ${job.data.scheduleNoteId} not found`);
} else {
data.note.createdAt = new Date();
const me = await this.usersRepository.findOneByOrFail({ id: data.userId });
await this.noteCreateService.create(me, data.note);
await this.noteScheduleRepository.remove(data);
}
});
} }
} }

View File

@ -109,28 +109,7 @@ export type EndedPollNotificationJobData = {
}; };
export type ScheduleNotePostJobData = { export type ScheduleNotePostJobData = {
note: { scheduleNoteId: MiNote['id'];
name?: string | null;
text?: string | null;
reply?: MiNote | null;
renote?: MiNote | null;
files?: MiDriveFile[] | null;
poll?: IPoll | null;
schedule?: MiNoteSchedule | null;
localOnly?: boolean | null;
reactionAcceptance?: MiNote['reactionAcceptance'];
cw?: string | null;
visibility?: string;
visibleUsers?: MinimumUser[] | null;
channel?: MiChannel | null;
apMentions?: MinimumUser[] | null;
apHashtags?: string[] | null;
apEmojis?: string[] | null;
uri?: string | null;
url?: string | null;
app?: MiApp | null;
};
user: MiUser & {host: null, uri: null};
} }
type MinimumUser = { type MinimumUser = {

View File

@ -7,7 +7,14 @@ import ms from 'ms';
import { DataSource, In } from 'typeorm'; import { DataSource, In } from 'typeorm';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import type { MiUser } from '@/models/User.js'; import type { MiUser } from '@/models/User.js';
import type { UsersRepository, NotesRepository, BlockingsRepository, DriveFilesRepository, ChannelsRepository } from '@/models/_.js'; import type {
UsersRepository,
NotesRepository,
BlockingsRepository,
DriveFilesRepository,
ChannelsRepository,
NoteScheduleRepository,
} from '@/models/_.js';
import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiDriveFile } from '@/models/DriveFile.js';
import type { MiNote } from '@/models/Note.js'; import type { MiNote } from '@/models/Note.js';
import type { MiChannel } from '@/models/Channel.js'; import type { MiChannel } from '@/models/Channel.js';
@ -18,6 +25,8 @@ import { NoteCreateService } from '@/core/NoteCreateService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { isPureRenote } from '@/misc/is-pure-renote.js'; import { isPureRenote } from '@/misc/is-pure-renote.js';
import { QueueService } from '@/core/QueueService.js'; import { QueueService } from '@/core/QueueService.js';
import { MiNoteSchedule } from '@/models/_.js';
import { IdService } from '@/core/IdService.js';
import { ApiError } from '../../error.js'; import { ApiError } from '../../error.js';
export const meta = { export const meta = {
@ -194,6 +203,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject(DI.notesRepository) @Inject(DI.notesRepository)
private notesRepository: NotesRepository, private notesRepository: NotesRepository,
@Inject(DI.noteScheduleRepository)
private noteScheduleRepository: NoteScheduleRepository,
@Inject(DI.blockingsRepository) @Inject(DI.blockingsRepository)
private blockingsRepository: BlockingsRepository, private blockingsRepository: BlockingsRepository,
@ -203,9 +215,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject(DI.channelsRepository) @Inject(DI.channelsRepository)
private channelsRepository: ChannelsRepository, private channelsRepository: ChannelsRepository,
private noteEntityService: NoteEntityService,
private queueService: QueueService, private queueService: QueueService,
private noteCreateService: NoteCreateService, private idService: IdService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(meta, paramDef, async (ps, me) => {
let visibleUsers: MiUser[] = []; let visibleUsers: MiUser[] = [];
@ -328,8 +339,28 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
} }
} }
} }
type NoteType = {
const note = { createdAt?: Date | undefined;
apEmojis: any[] | undefined;
visibility: any;
apMentions: any[] | undefined;
visibleUsers: MiUser[];
channel: null | MiChannel;
poll: {
multiple: any;
choices: any;
expiresAt: Date | null;
} | undefined;
renote: null | MiNote;
localOnly: any;
cw: any;
apHashtags: any[] | undefined;
reactionAcceptance: any;
files: MiDriveFile[];
text: any;
reply: null | MiNote;
};
const note:NoteType = {
files: files, files: files,
poll: ps.poll ? { poll: ps.poll ? {
choices: ps.poll.choices, choices: ps.poll.choices,
@ -351,10 +382,17 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}; };
if (ps.schedule && ps.schedule.expiresAt) { if (ps.schedule && ps.schedule.expiresAt) {
me.token = null;
const noteId = this.idService.gen(new Date().getTime());
await this.noteScheduleRepository.insert({
id: noteId,
note: note,
userId: me.id,
});
const delay = new Date(ps.schedule.expiresAt).getTime() - Date.now(); const delay = new Date(ps.schedule.expiresAt).getTime() - Date.now();
await this.queueService.ScheduleNotePostQueue.add(String(delay), { await this.queueService.ScheduleNotePostQueue.add(String(delay), {
note: note, scheduleNoteId: noteId,
user: me,
}, { }, {
delay, delay,
removeOnComplete: true, removeOnComplete: true,