dbに保存するようにした
Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
This commit is contained in:
parent
e133a6b6a4
commit
387faf55cf
|
@ -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",
|
||||||
|
|
|
@ -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"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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'];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue