Add notification plugin hook
This commit is contained in:
parent
0260dc8aca
commit
785f1897a4
|
@ -7,12 +7,12 @@ import { MAbuseFull, MAbuseMessage, MActorFollowFull, MApplication, MPlugin } fr
|
||||||
import { MCommentOwnerVideo, MVideoAccountLight, MVideoFullLight } from '../../types/models/video'
|
import { MCommentOwnerVideo, MVideoAccountLight, MVideoFullLight } from '../../types/models/video'
|
||||||
import { JobQueue } from '../job-queue'
|
import { JobQueue } from '../job-queue'
|
||||||
import { PeerTubeSocket } from '../peertube-socket'
|
import { PeerTubeSocket } from '../peertube-socket'
|
||||||
|
import { Hooks } from '../plugins/hooks'
|
||||||
import {
|
import {
|
||||||
AbstractNotification,
|
AbstractNotification,
|
||||||
AbuseStateChangeForReporter,
|
AbuseStateChangeForReporter,
|
||||||
AutoFollowForInstance,
|
AutoFollowForInstance,
|
||||||
CommentMention,
|
CommentMention,
|
||||||
StudioEditionFinishedForOwner,
|
|
||||||
FollowForInstance,
|
FollowForInstance,
|
||||||
FollowForUser,
|
FollowForUser,
|
||||||
ImportFinishedForOwner,
|
ImportFinishedForOwner,
|
||||||
|
@ -31,6 +31,7 @@ import {
|
||||||
OwnedPublicationAfterScheduleUpdate,
|
OwnedPublicationAfterScheduleUpdate,
|
||||||
OwnedPublicationAfterTranscoding,
|
OwnedPublicationAfterTranscoding,
|
||||||
RegistrationForModerators,
|
RegistrationForModerators,
|
||||||
|
StudioEditionFinishedForOwner,
|
||||||
UnblacklistForOwner
|
UnblacklistForOwner
|
||||||
} from './shared'
|
} from './shared'
|
||||||
|
|
||||||
|
@ -222,15 +223,21 @@ class Notifier {
|
||||||
for (const user of users) {
|
for (const user of users) {
|
||||||
const setting = object.getSetting(user)
|
const setting = object.getSetting(user)
|
||||||
|
|
||||||
if (this.isWebNotificationEnabled(setting)) {
|
const webNotificationEnabled = this.isWebNotificationEnabled(setting)
|
||||||
const notification = await object.createNotification(user)
|
const emailNotificationEnabled = this.isEmailEnabled(user, setting)
|
||||||
|
const notification = object.createNotification(user)
|
||||||
|
|
||||||
|
if (webNotificationEnabled) {
|
||||||
|
await notification.save()
|
||||||
|
|
||||||
PeerTubeSocket.Instance.sendNotification(user.id, notification)
|
PeerTubeSocket.Instance.sendNotification(user.id, notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isEmailEnabled(user, setting)) {
|
if (emailNotificationEnabled) {
|
||||||
toEmails.push(user.email)
|
toEmails.push(user.email)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Hooks.runAction('action:notifier.notification.created', { webNotificationEnabled, emailNotificationEnabled, user, notification })
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const to of toEmails) {
|
for (const to of toEmails) {
|
||||||
|
|
|
@ -21,8 +21,8 @@ export abstract class AbstractNewAbuseMessage extends AbstractNotification <NewA
|
||||||
return user.NotificationSetting.abuseNewMessage
|
return user.NotificationSetting.abuseNewMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.ABUSE_NEW_MESSAGE,
|
type: UserNotificationType.ABUSE_NEW_MESSAGE,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
abuseId: this.abuse.id
|
abuseId: this.abuse.id
|
||||||
|
|
|
@ -32,8 +32,8 @@ export class AbuseStateChangeForReporter extends AbstractNotification <MAbuseFul
|
||||||
return [ this.user ]
|
return [ this.user ]
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.ABUSE_STATE_CHANGE,
|
type: UserNotificationType.ABUSE_STATE_CHANGE,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
abuseId: this.abuse.id
|
abuseId: this.abuse.id
|
||||||
|
|
|
@ -28,8 +28,8 @@ export class NewAbuseForModerators extends AbstractNotification <NewAbusePayload
|
||||||
return this.moderators
|
return this.moderators
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.NEW_ABUSE_FOR_MODERATORS,
|
type: UserNotificationType.NEW_ABUSE_FOR_MODERATORS,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
abuseId: this.payload.abuseInstance.id
|
abuseId: this.payload.abuseInstance.id
|
||||||
|
|
|
@ -26,8 +26,8 @@ export class NewAutoBlacklistForModerators extends AbstractNotification <MVideoB
|
||||||
return this.moderators
|
return this.moderators
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS,
|
type: UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
videoBlacklistId: this.payload.id
|
videoBlacklistId: this.payload.id
|
||||||
|
|
|
@ -28,8 +28,8 @@ export class NewBlacklistForOwner extends AbstractNotification <MVideoBlacklistV
|
||||||
return [ this.user ]
|
return [ this.user ]
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.BLACKLIST_ON_MY_VIDEO,
|
type: UserNotificationType.BLACKLIST_ON_MY_VIDEO,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
videoBlacklistId: this.payload.id
|
videoBlacklistId: this.payload.id
|
||||||
|
|
|
@ -28,8 +28,8 @@ export class UnblacklistForOwner extends AbstractNotification <MVideoFullLight>
|
||||||
return [ this.user ]
|
return [ this.user ]
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.UNBLACKLIST_ON_MY_VIDEO,
|
type: UserNotificationType.UNBLACKLIST_ON_MY_VIDEO,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
videoId: this.payload.id
|
videoId: this.payload.id
|
||||||
|
|
|
@ -71,8 +71,8 @@ export class CommentMention extends AbstractNotification <MCommentOwnerVideo, MU
|
||||||
return this.users
|
return this.users
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.COMMENT_MENTION,
|
type: UserNotificationType.COMMENT_MENTION,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
commentId: this.payload.id
|
commentId: this.payload.id
|
||||||
|
|
|
@ -38,8 +38,8 @@ export class NewCommentForVideoOwner extends AbstractNotification <MCommentOwner
|
||||||
return [ this.user ]
|
return [ this.user ]
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.NEW_COMMENT_ON_MY_VIDEO,
|
type: UserNotificationType.NEW_COMMENT_ON_MY_VIDEO,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
commentId: this.payload.id
|
commentId: this.payload.id
|
||||||
|
|
|
@ -13,7 +13,7 @@ export abstract class AbstractNotification <T, U = MUserWithNotificationSetting>
|
||||||
abstract getSetting (user: U): UserNotificationSettingValue
|
abstract getSetting (user: U): UserNotificationSettingValue
|
||||||
abstract getTargetUsers (): U[]
|
abstract getTargetUsers (): U[]
|
||||||
|
|
||||||
abstract createNotification (user: U): Promise<UserNotificationModelForApi>
|
abstract createNotification (user: U): UserNotificationModelForApi
|
||||||
abstract createEmail (to: string): EmailPayload | Promise<EmailPayload>
|
abstract createEmail (to: string): EmailPayload | Promise<EmailPayload>
|
||||||
|
|
||||||
isDisabled (): boolean | Promise<boolean> {
|
isDisabled (): boolean | Promise<boolean> {
|
||||||
|
|
|
@ -24,8 +24,8 @@ export class AutoFollowForInstance extends AbstractNotification <MActorFollowFul
|
||||||
return this.admins
|
return this.admins
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.AUTO_INSTANCE_FOLLOWING,
|
type: UserNotificationType.AUTO_INSTANCE_FOLLOWING,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
actorFollowId: this.actorFollow.id
|
actorFollowId: this.actorFollow.id
|
||||||
|
|
|
@ -32,8 +32,8 @@ export class FollowForInstance extends AbstractNotification <MActorFollowFull> {
|
||||||
return this.admins
|
return this.admins
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.NEW_INSTANCE_FOLLOWER,
|
type: UserNotificationType.NEW_INSTANCE_FOLLOWER,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
actorFollowId: this.actorFollow.id
|
actorFollowId: this.actorFollow.id
|
||||||
|
|
|
@ -45,8 +45,8 @@ export class FollowForUser extends AbstractNotification <MActorFollowFull> {
|
||||||
return [ this.user ]
|
return [ this.user ]
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.NEW_FOLLOW,
|
type: UserNotificationType.NEW_FOLLOW,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
actorFollowId: this.actorFollow.id
|
actorFollowId: this.actorFollow.id
|
||||||
|
|
|
@ -30,8 +30,8 @@ export class NewPeerTubeVersionForAdmins extends AbstractNotification <NewPeerTu
|
||||||
return this.admins
|
return this.admins
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.NEW_PEERTUBE_VERSION,
|
type: UserNotificationType.NEW_PEERTUBE_VERSION,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
applicationId: this.payload.application.id
|
applicationId: this.payload.application.id
|
||||||
|
|
|
@ -26,8 +26,8 @@ export class NewPluginVersionForAdmins extends AbstractNotification <MPlugin> {
|
||||||
return this.admins
|
return this.admins
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.NEW_PLUGIN_VERSION,
|
type: UserNotificationType.NEW_PLUGIN_VERSION,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
pluginId: this.plugin.id
|
pluginId: this.plugin.id
|
||||||
|
|
|
@ -25,8 +25,8 @@ export class RegistrationForModerators extends AbstractNotification <MUserDefaul
|
||||||
return this.moderators
|
return this.moderators
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.NEW_USER_REGISTRATION,
|
type: UserNotificationType.NEW_USER_REGISTRATION,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
accountId: this.payload.Account.id
|
accountId: this.payload.Account.id
|
||||||
|
|
|
@ -27,8 +27,8 @@ export abstract class AbstractOwnedVideoPublication extends AbstractNotification
|
||||||
return [ this.user ]
|
return [ this.user ]
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.MY_VIDEO_PUBLISHED,
|
type: UserNotificationType.MY_VIDEO_PUBLISHED,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
videoId: this.payload.id
|
videoId: this.payload.id
|
||||||
|
|
|
@ -32,8 +32,8 @@ export class ImportFinishedForOwner extends AbstractNotification <ImportFinished
|
||||||
return [ this.user ]
|
return [ this.user ]
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: this.payload.success
|
type: this.payload.success
|
||||||
? UserNotificationType.MY_VIDEO_IMPORT_SUCCESS
|
? UserNotificationType.MY_VIDEO_IMPORT_SUCCESS
|
||||||
: UserNotificationType.MY_VIDEO_IMPORT_ERROR,
|
: UserNotificationType.MY_VIDEO_IMPORT_ERROR,
|
||||||
|
|
|
@ -30,8 +30,8 @@ export class NewVideoForSubscribers extends AbstractNotification <MVideoAccountL
|
||||||
return this.users
|
return this.users
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION,
|
type: UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
videoId: this.payload.id
|
videoId: this.payload.id
|
||||||
|
|
|
@ -27,8 +27,8 @@ export class StudioEditionFinishedForOwner extends AbstractNotification <MVideoF
|
||||||
return [ this.user ]
|
return [ this.user ]
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = UserNotificationModel.build<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.MY_VIDEO_STUDIO_EDITION_FINISHED,
|
type: UserNotificationType.MY_VIDEO_STUDIO_EDITION_FINISHED,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
videoId: this.payload.id
|
videoId: this.payload.id
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
async function register ({ registerHook, registerSetting, settingsManager, storageManager, peertubeHelpers }) {
|
async function register ({ registerHook, registerSetting, settingsManager, storageManager, peertubeHelpers }) {
|
||||||
const actionHooks = [
|
const actionHooks = [
|
||||||
'action:application.listening',
|
'action:application.listening',
|
||||||
|
'action:notifier.notification.created',
|
||||||
|
|
||||||
'action:api.video.updated',
|
'action:api.video.updated',
|
||||||
'action:api.video.deleted',
|
'action:api.video.deleted',
|
||||||
|
|
|
@ -17,8 +17,8 @@ describe('Test plugin action hooks', function () {
|
||||||
let videoUUID: string
|
let videoUUID: string
|
||||||
let threadId: number
|
let threadId: number
|
||||||
|
|
||||||
function checkHook (hook: ServerHookName) {
|
function checkHook (hook: ServerHookName, strictCount = true) {
|
||||||
return servers[0].servers.waitUntilLog('Run hook ' + hook)
|
return servers[0].servers.waitUntilLog('Run hook ' + hook, 1, strictCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
|
@ -225,6 +225,13 @@ describe('Test plugin action hooks', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('Notification hook', function () {
|
||||||
|
|
||||||
|
it('Should run action:notifier.notification.created', async function () {
|
||||||
|
await checkHook('action:notifier.notification.created', false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
await cleanupTests(servers)
|
await cleanupTests(servers)
|
||||||
})
|
})
|
||||||
|
|
|
@ -112,6 +112,9 @@ export const serverActionHookObject = {
|
||||||
// Fired when the application has been loaded and is listening HTTP requests
|
// Fired when the application has been loaded and is listening HTTP requests
|
||||||
'action:application.listening': true,
|
'action:application.listening': true,
|
||||||
|
|
||||||
|
// Fired when a new notification is created
|
||||||
|
'action:notifier.notification.created': true,
|
||||||
|
|
||||||
// API actions hooks give access to the original express `req` and `res` parameters
|
// API actions hooks give access to the original express `req` and `res` parameters
|
||||||
|
|
||||||
// Fired when a local video is updated
|
// Fired when a local video is updated
|
||||||
|
|
Loading…
Reference in New Issue