Skip to content

Commit

Permalink
予約投稿
Browse files Browse the repository at this point in the history
cherrypick from Type4ny-Project/Type4ny@e133a6b

Co-authored-by: まっちゃてぃー。 <[email protected]>Signed-off-by: mattyatea <[email protected]>

# Conflicts:
#	locales/index.d.ts
#	misskey-assets
#	packages/backend/src/core/NoteCreateService.ts
#	packages/backend/src/core/QueueModule.ts
#	packages/backend/src/core/QueueService.ts
#	packages/backend/src/di-symbols.ts
#	packages/backend/src/models/_.ts
#	packages/backend/src/queue/types.ts
#	packages/backend/src/server/api/endpoints/admin/queue/stats.ts
#	packages/backend/src/server/web/ClientServerService.ts
#	packages/frontend/src/components/MkPostForm.vue
  • Loading branch information
mattyatea authored and kozakura913 committed Sep 28, 2024
1 parent a7b8df8 commit de02ac8
Show file tree
Hide file tree
Showing 26 changed files with 731 additions and 7 deletions.
4 changes: 4 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2946,6 +2946,10 @@ export interface Locale extends ILocale {
* アンケート
*/
"poll": string;
/**
* 予約
*/
"schedule": string;
/**
* 内容を隠す
*/
Expand Down
1 change: 1 addition & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,7 @@ invisibleNote: "非公開の投稿"
enableInfiniteScroll: "自動でもっと見る"
visibility: "公開範囲"
poll: "アンケート"
schedule: "予約"
useCw: "内容を隠す"
enablePlayer: "プレイヤーを開く"
disablePlayer: "プレイヤーを閉じる"
Expand Down
3 changes: 2 additions & 1 deletion packages/backend/src/core/NoteCreateService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import { UserBlockingService } from '@/core/UserBlockingService.js';
import { isReply } from '@/misc/is-reply.js';
import { trackPromise } from '@/misc/promise-tracker.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';
import { MiNoteSchedule } from '@/models/_.js';

type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';

Expand Down Expand Up @@ -139,6 +140,7 @@ type Option = {
files?: MiDriveFile[] | null;
poll?: IPoll | null;
event?: IEvent | null;
schedule?: MiNoteSchedule | null;
localOnly?: boolean | null;
reactionAcceptance?: MiNote['reactionAcceptance'];
disableRightClick?: boolean | null;
Expand Down Expand Up @@ -400,7 +402,6 @@ export class NoteCreateService implements OnApplicationShutdown {
if (mentionedUsers.length > 0 && mentionedUsers.length > (await this.roleService.getUserPolicies(user.id)).mentionLimit) {
throw new IdentifiableError('9f466dab-c856-48cd-9e65-ff90ff750580', 'Note contains too many mentions');
}

const note = await this.insertNote(user, data, tags, emojis, mentionedUsers);

setImmediate('post created', { signal: this.#shutdownController.signal }).then(
Expand Down
12 changes: 12 additions & 0 deletions packages/backend/src/core/QueueModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ import {
RelationshipJobData,
UserWebhookDeliverJobData,
SystemWebhookDeliverJobData,
ScheduleNotePostJobData,
} from '../queue/types.js';
import type { Provider } from '@nestjs/common';

export type SystemQueue = Bull.Queue<Record<string, unknown>>;
export type EndedPollNotificationQueue = Bull.Queue<EndedPollNotificationJobData>;
export type ScheduleNotePostQueue = Bull.Queue<ScheduleNotePostJobData>;
export type DeliverQueue = Bull.Queue<DeliverJobData>;
export type InboxQueue = Bull.Queue<InboxJobData>;
export type DbQueue = Bull.Queue;
Expand All @@ -42,6 +44,12 @@ const $endedPollNotification: Provider = {
inject: [DI.config, DI.redisForJobQueue],
};

const $scheduleNotePost: Provider = {
provide: 'queue:scheduleNotePost',
useFactory: (config: Config, redisForJobQueue: Redis.Redis) => new Bull.Queue(QUEUE.SCHEDULE_NOTE_POST, baseQueueOptions(config, QUEUE.SCHEDULE_NOTE_POST, redisForJobQueue)),
inject: [DI.config, DI.redisForJobQueue],
};

const $deliver: Provider = {
provide: 'queue:deliver',
useFactory: (config: Config, redisForJobQueue: Redis.Redis) => new Bull.Queue(QUEUE.DELIVER, baseQueueOptions(config, QUEUE.DELIVER, redisForJobQueue)),
Expand Down Expand Up @@ -90,6 +98,7 @@ const $systemWebhookDeliver: Provider = {
providers: [
$system,
$endedPollNotification,
$scheduleNotePost,
$deliver,
$inbox,
$db,
Expand All @@ -101,6 +110,7 @@ const $systemWebhookDeliver: Provider = {
exports: [
$system,
$endedPollNotification,
$scheduleNotePost,
$deliver,
$inbox,
$db,
Expand All @@ -114,6 +124,7 @@ export class QueueModule implements OnApplicationShutdown {
constructor(
@Inject('queue:system') public systemQueue: SystemQueue,
@Inject('queue:endedPollNotification') public endedPollNotificationQueue: EndedPollNotificationQueue,
@Inject('queue:scheduleNotePost') public scheduleNotePostQueue: ScheduleNotePostQueue,
@Inject('queue:deliver') public deliverQueue: DeliverQueue,
@Inject('queue:inbox') public inboxQueue: InboxQueue,
@Inject('queue:db') public dbQueue: DbQueue,
Expand All @@ -130,6 +141,7 @@ export class QueueModule implements OnApplicationShutdown {
await Promise.all([
this.systemQueue.close(),
this.endedPollNotificationQueue.close(),
this.scheduleNotePostQueue.close(),
this.deliverQueue.close(),
this.inboxQueue.close(),
this.dbQueue.close(),
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/core/QueueService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import type {
SystemQueue,
UserWebhookDeliverQueue,
SystemWebhookDeliverQueue,
ScheduleNotePostQueue,
} from './QueueModule.js';
import type httpSignature from '@peertube/http-signature';
import type * as Bull from 'bullmq';
Expand All @@ -45,6 +46,7 @@ export class QueueService {

@Inject('queue:system') public systemQueue: SystemQueue,
@Inject('queue:endedPollNotification') public endedPollNotificationQueue: EndedPollNotificationQueue,
@Inject('queue:scheduleNotePost') public ScheduleNotePostQueue: ScheduleNotePostQueue,
@Inject('queue:deliver') public deliverQueue: DeliverQueue,
@Inject('queue:inbox') public inboxQueue: InboxQueue,
@Inject('queue:db') public dbQueue: DbQueue,
Expand Down
1 change: 1 addition & 0 deletions packages/backend/src/di-symbols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const DI = {
//#region Repositories
usersRepository: Symbol('usersRepository'),
notesRepository: Symbol('notesRepository'),
noteScheduleRepository: Symbol('noteScheduleRepository'),
abuseReportResolversRepository: Symbol('abuseReportResolversRepository'),
announcementsRepository: Symbol('announcementsRepository'),
announcementReadsRepository: Symbol('announcementReadsRepository'),
Expand Down
29 changes: 29 additions & 0 deletions packages/backend/src/models/NoteSchedule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm';
import { noteVisibilities } from '@/types.js';
import { MiNote } from '@/models/Note.js';
import { id } from './util/id.js';
import { MiUser } from './User.js';
import { MiChannel } from './Channel.js';
import type { MiDriveFile } from './DriveFile.js';

@Entity('note_schedule')
export class MiNoteSchedule {
@PrimaryColumn(id())
public noteId: MiNote['id'];

@Column('string')
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 };

@Column('string')
public user: MiUser & {host: null;uri: null;};

@Column('timestamp with time zone', {
nullable: true,
})
public expiresAt: Date;
}
3 changes: 3 additions & 0 deletions packages/backend/src/models/_.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ import { MiFlash } from '@/models/Flash.js';
import { MiFlashLike } from '@/models/FlashLike.js';
import { MiFlashLikeRemote } from '@/models/FlashLikeRemote.js';
import { MiUserListFavorite } from '@/models/UserListFavorite.js';
import { MiNoteSchedule } from './NoteSchedule.js';
import { MiBubbleGameRecord } from '@/models/BubbleGameRecord.js';
import { MiReversiGame } from '@/models/ReversiGame.js';
import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js';
Expand Down Expand Up @@ -173,6 +174,7 @@ export {
MiNoteThreadMuting,
MiNoteUnread,
MiOfficialTag,
MiNoteSchedule,
MiPage,
MiPageLike,
MiPasswordResetRequest,
Expand Down Expand Up @@ -253,6 +255,7 @@ export type NoteReactionsRepository = Repository<MiNoteReaction> & MiRepository<
export type NoteThreadMutingsRepository = Repository<MiNoteThreadMuting> & MiRepository<MiNoteThreadMuting>;
export type NoteUnreadsRepository = Repository<MiNoteUnread> & MiRepository<MiNoteUnread>;
export type OfficialTagRepository = Repository<MiOfficialTag> & MiRepository<MiOfficialTag>;
export type NoteScheduleRepository = Repository<MiNoteSchedule>;
export type PagesRepository = Repository<MiPage> & MiRepository<MiPage>;
export type PageLikesRepository = Repository<MiPageLike> & MiRepository<MiPageLike>;
export type PasswordResetRequestsRepository = Repository<MiPasswordResetRequest> & MiRepository<MiPasswordResetRequest>;
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/queue/QueueProcessorModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { QueueLoggerService } from './QueueLoggerService.js';
import { QueueProcessorService } from './QueueProcessorService.js';
import { DeliverProcessorService } from './processors/DeliverProcessorService.js';
import { EndedPollNotificationProcessorService } from './processors/EndedPollNotificationProcessorService.js';
import { ScheduleNotePostProcessorService } from './processors/ScheduleNotePostProcessorService.js';
import { InboxProcessorService } from './processors/InboxProcessorService.js';
import { UserWebhookDeliverProcessorService } from './processors/UserWebhookDeliverProcessorService.js';
import { SystemWebhookDeliverProcessorService } from './processors/SystemWebhookDeliverProcessorService.js';
Expand Down Expand Up @@ -77,6 +78,7 @@ import { RelationshipProcessorService } from './processors/RelationshipProcessor
UserWebhookDeliverProcessorService,
SystemWebhookDeliverProcessorService,
EndedPollNotificationProcessorService,
ScheduleNotePostProcessorService,
DeliverProcessorService,
InboxProcessorService,
AggregateRetentionProcessorService,
Expand Down
12 changes: 12 additions & 0 deletions packages/backend/src/queue/QueueProcessorService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { bindThis } from '@/decorators.js';
import { UserWebhookDeliverProcessorService } from './processors/UserWebhookDeliverProcessorService.js';
import { SystemWebhookDeliverProcessorService } from './processors/SystemWebhookDeliverProcessorService.js';
import { EndedPollNotificationProcessorService } from './processors/EndedPollNotificationProcessorService.js';
import { ScheduleNotePostProcessorService } from './processors/ScheduleNotePostProcessorService.js';
import { DeliverProcessorService } from './processors/DeliverProcessorService.js';
import { InboxProcessorService } from './processors/InboxProcessorService.js';
import { DeleteDriveFilesProcessorService } from './processors/DeleteDriveFilesProcessorService.js';
Expand Down Expand Up @@ -84,6 +85,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
private relationshipQueueWorker: Bull.Worker;
private objectStorageQueueWorker: Bull.Worker;
private endedPollNotificationQueueWorker: Bull.Worker;
private schedulerNotePostQueueWorker: Bull.Worker;

constructor(
@Inject(DI.config)
Expand All @@ -96,6 +98,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
private userWebhookDeliverProcessorService: UserWebhookDeliverProcessorService,
private systemWebhookDeliverProcessorService: SystemWebhookDeliverProcessorService,
private endedPollNotificationProcessorService: EndedPollNotificationProcessorService,
private scheduleNotePostProcessorService: ScheduleNotePostProcessorService,
private deliverProcessorService: DeliverProcessorService,
private inboxProcessorService: InboxProcessorService,
private deleteDriveFilesProcessorService: DeleteDriveFilesProcessorService,
Expand Down Expand Up @@ -494,6 +497,13 @@ export class QueueProcessorService implements OnApplicationShutdown {
}
//#endregion

//#region schedule note post
this.schedulerNotePostQueueWorker = new Bull.Worker(QUEUE.SCHEDULE_NOTE_POST, (job) => this.scheduleNotePostProcessorService.process(job), {
...baseQueueOptions(this.config, QUEUE.SCHEDULE_NOTE_POST, this.redisForJobQueue),
autorun: false,
});
//#endregion

//#region ended poll notification
{
this.endedPollNotificationQueueWorker = new Bull.Worker(QUEUE.ENDED_POLL_NOTIFICATION, (job) => {
Expand Down Expand Up @@ -522,6 +532,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
this.relationshipQueueWorker.run(),
this.objectStorageQueueWorker.run(),
this.endedPollNotificationQueueWorker.run(),
this.schedulerNotePostQueueWorker.run(),
]);
}

Expand All @@ -537,6 +548,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
this.relationshipQueueWorker.close(),
this.objectStorageQueueWorker.close(),
this.endedPollNotificationQueueWorker.close(),
this.schedulerNotePostQueueWorker.close(),
]);
}

Expand Down
1 change: 1 addition & 0 deletions packages/backend/src/queue/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const QUEUE = {
INBOX: 'inbox',
SYSTEM: 'system',
ENDED_POLL_NOTIFICATION: 'endedPollNotification',
SCHEDULE_NOTE_POST: 'scheduleNotePost',
DB: 'db',
RELATIONSHIP: 'relationship',
OBJECT_STORAGE: 'objectStorage',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { Inject, Injectable } from '@nestjs/common';
import type Logger from '@/logger.js';
import { bindThis } from '@/decorators.js';
import { NoteCreateService } from '@/core/NoteCreateService.js';
import { QueueLoggerService } from '../QueueLoggerService.js';
import type * as Bull from 'bullmq';
import type { ScheduleNotePostJobData } from '../types.js';

@Injectable()
export class ScheduleNotePostProcessorService {
private logger: Logger;

constructor(
private noteCreateService: NoteCreateService,
private queueLoggerService: QueueLoggerService,
) {
this.logger = this.queueLoggerService.logger.createSubLogger('ended-poll-notification');
}

@bindThis
public async process(job: Bull.Job<ScheduleNotePostJobData>): Promise<void> {
job.data.note.createdAt = new Date();
await this.noteCreateService.create(job.data.user, job.data.note);
}
}
38 changes: 37 additions & 1 deletion packages/backend/src/queue/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@
import type { Antenna } from '@/server/api/endpoints/i/import-antennas.js';
import type { MiDriveFile } from '@/models/DriveFile.js';
import type { MiNote } from '@/models/Note.js';
import type { MiUser } from '@/models/User.js';
import type { MiLocalUser, MiUser } from '@/models/User.js';
import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js';
import type { MiWebhook } from '@/models/Webhook.js';
import type { IActivity } from '@/core/activitypub/type.js';
import { IPoll } from '@/models/Poll.js';
import { MiNoteSchedule } from '@/models/NoteSchedule.js';
import { MiChannel } from '@/models/Channel.js';
import { MiApp } from '@/models/App.js';
import type httpSignature from '@peertube/http-signature';

export type DeliverJobData = {
Expand Down Expand Up @@ -109,6 +113,38 @@ export type EndedPollNotificationJobData = {
noteId: MiNote['id'];
};

export type ScheduleNotePostJobData = {
note: {
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 = {
id: MiUser['id'];
host: MiUser['host'];
username: MiUser['username'];
uri: MiUser['uri'];
};

export type SystemWebhookDeliverJobData = {
type: string;
content: unknown;
Expand Down
4 changes: 4 additions & 0 deletions packages/backend/src/server/api/EndpointsModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ import * as ep___notes_children from './endpoints/notes/children.js';
import * as ep___notes_clips from './endpoints/notes/clips.js';
import * as ep___notes_conversation from './endpoints/notes/conversation.js';
import * as ep___notes_create from './endpoints/notes/create.js';
import * as ep___notes_schedule_create from './endpoints/notes/create-schedule.js';
import * as ep___notes_delete from './endpoints/notes/delete.js';
import * as ep___notes_update from './endpoints/notes/update.js';
import * as ep___notes_favorites_create from './endpoints/notes/favorites/create.js';
Expand Down Expand Up @@ -695,6 +696,7 @@ const $notes_children: Provider = { provide: 'ep:notes/children', useClass: ep__
const $notes_clips: Provider = { provide: 'ep:notes/clips', useClass: ep___notes_clips.default };
const $notes_conversation: Provider = { provide: 'ep:notes/conversation', useClass: ep___notes_conversation.default };
const $notes_create: Provider = { provide: 'ep:notes/create', useClass: ep___notes_create.default };
const $notes_schedule_create: Provider = { provide: 'ep:notes/create-schedule', useClass: ep___notes_schedule_create.default };
const $notes_delete: Provider = { provide: 'ep:notes/delete', useClass: ep___notes_delete.default };
const $notes_update: Provider = { provide: 'ep:notes/update', useClass: ep___notes_update.default };
const $notes_favorites_create: Provider = { provide: 'ep:notes/favorites/create', useClass: ep___notes_favorites_create.default };
Expand Down Expand Up @@ -1110,6 +1112,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__
$notes_clips,
$notes_conversation,
$notes_create,
$notes_schedule_create,
$notes_delete,
$notes_update,
$notes_favorites_create,
Expand Down Expand Up @@ -1517,6 +1520,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__
$notes_clips,
$notes_conversation,
$notes_create,
$notes_schedule_create,
$notes_delete,
$notes_update,
$notes_favorites_create,
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/server/api/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ import * as ep___notes_children from './endpoints/notes/children.js';
import * as ep___notes_clips from './endpoints/notes/clips.js';
import * as ep___notes_conversation from './endpoints/notes/conversation.js';
import * as ep___notes_create from './endpoints/notes/create.js';
import * as ep___notes_schedule_create from './endpoints/notes/create-schedule.js';
import * as ep___notes_delete from './endpoints/notes/delete.js';
import * as ep___notes_update from './endpoints/notes/update.js';
import * as ep___notes_favorites_create from './endpoints/notes/favorites/create.js';
Expand Down Expand Up @@ -698,6 +699,7 @@ const eps = [
['notes/clips', ep___notes_clips],
['notes/conversation', ep___notes_conversation],
['notes/create', ep___notes_create],
['notes/create-schedule', ep___notes_schedule_create],
['notes/delete', ep___notes_delete],
['notes/update', ep___notes_update],
['notes/favorites/create', ep___notes_favorites_create],
Expand Down
Loading

0 comments on commit de02ac8

Please sign in to comment.