Add notification on subscription live stream

This commit is contained in:
Chocobozzz
2024-02-15 13:55:12 +01:00
parent 4300cc1ee1
commit a012d6c2a9
19 changed files with 273 additions and 55 deletions

View File

@@ -34,7 +34,9 @@ export const UserNotificationType = {
MY_VIDEO_STUDIO_EDITION_FINISHED: 19,
NEW_USER_REGISTRATION_REQUEST: 20
NEW_USER_REGISTRATION_REQUEST: 20,
NEW_LIVE_FROM_SUBSCRIPTION: 21
} as const
export type UserNotificationType_Type = typeof UserNotificationType[keyof typeof UserNotificationType]

View File

@@ -119,12 +119,13 @@ export class LiveCommand extends AbstractCommand {
}
async quickCreate (options: OverrideCommandOptions & {
name: string
saveReplay: boolean
permanentLive: boolean
privacy?: VideoPrivacyType
videoPasswords?: string[]
}) {
const { saveReplay, permanentLive, privacy = VideoPrivacy.PUBLIC, videoPasswords } = options
const { name = 'live', saveReplay, permanentLive, privacy = VideoPrivacy.PUBLIC, videoPasswords } = options
const replaySettings = privacy === VideoPrivacy.PASSWORD_PROTECTED
? { privacy: VideoPrivacy.PRIVATE }
@@ -134,7 +135,7 @@ export class LiveCommand extends AbstractCommand {
...options,
fields: {
name: 'live',
name,
permanentLive,
saveReplay,
replaySettings,

View File

@@ -18,7 +18,7 @@ import {
checkNewInstanceFollower,
checkAutoInstanceFollowing,
checkVideoAutoBlacklistForModerators,
checkVideoIsPublished,
checkMyVideoIsPublished,
checkNewVideoFromSubscription
} from '@tests/shared/notifications.js'
@@ -487,7 +487,7 @@ describe('Test moderation notifications', function () {
it('Should not send video publish notification if auto-blacklisted', async function () {
this.timeout(120000)
await checkVideoIsPublished({ ...userBaseParams, videoName, shortUUID, checkType: 'absence' })
await checkMyVideoIsPublished({ ...userBaseParams, videoName, shortUUID, checkType: 'absence' })
})
it('Should not send a local user subscription notification if auto-blacklisted', async function () {
@@ -576,7 +576,7 @@ describe('Test moderation notifications', function () {
const { shortUUID } = await servers[0].videos.upload({ token: userToken1, attributes })
await wait(6000)
await checkVideoIsPublished({ ...userBaseParams, videoName: name, shortUUID, checkType: 'absence' })
await checkMyVideoIsPublished({ ...userBaseParams, videoName: name, shortUUID, checkType: 'absence' })
await checkNewVideoFromSubscription({ ...adminBaseParamsServer1, videoName: name, shortUUID, checkType: 'absence' })
await checkNewVideoFromSubscription({ ...adminBaseParamsServer2, videoName: name, shortUUID, checkType: 'absence' })
})

View File

@@ -10,10 +10,12 @@ import {
prepareNotificationsTest,
CheckerBaseParams,
checkNewVideoFromSubscription,
checkVideoIsPublished,
checkMyVideoIsPublished,
checkVideoStudioEditionIsFinished,
checkMyVideoImportIsFinished,
checkNewActorFollow
checkNewActorFollow,
checkNewLiveFromSubscription,
waitUntilNotification
} from '@tests/shared/notifications.js'
import { FIXTURE_URLS } from '@tests/shared/tests.js'
import { uploadRandomVideoOnServers } from '@tests/shared/videos.js'
@@ -209,6 +211,82 @@ describe('Test user notifications', function () {
await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID: video.shortUUID, checkType: 'presence' })
})
})
describe('New live from my subscription notification', function () {
let baseParams: CheckerBaseParams
async function createAndStreamLive (server: PeerTubeServer) {
const name = 'video live ' + buildUUID()
const streamDate = new Date()
const { video } = await server.live.quickCreate({ name, permanentLive: true, saveReplay: false })
await waitJobs(servers)
const ffmpegCommand = await server.live.sendRTMPStreamInVideo({ videoId: video.uuid })
return { name, video, ffmpegCommand, streamDate }
}
before(async () => {
baseParams = {
server: servers[0],
emails,
socketNotifications: userNotifications,
token: userAccessToken
}
await servers[0].config.enableLive({ allowReplay: false })
await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'root_channel@' + servers[0].host })
await waitJobs(servers)
})
it('Should not send a notification when a live is created', async function () {
this.timeout(100000)
const name = 'video live ' + buildUUID()
const { video } = await servers[0].live.quickCreate({ name, permanentLive: true, saveReplay: false })
await waitJobs(servers)
await checkNewLiveFromSubscription({ ...baseParams, videoName: name, shortUUID: video.shortUUID, checkType: 'absence' })
})
it('Should send a local notification when streaming in the live', async function () {
this.timeout(100000)
const { name, video, ffmpegCommand, streamDate } = await createAndStreamLive(servers[0])
await waitUntilNotification({
server: servers[0],
token: userAccessToken,
notificationType: UserNotificationType.NEW_LIVE_FROM_SUBSCRIPTION,
fromDate: streamDate
})
await checkNewLiveFromSubscription({ ...baseParams, videoName: name, shortUUID: video.shortUUID, checkType: 'presence' })
await stopFfmpeg(ffmpegCommand)
await waitJobs(servers)
})
it('Should send a remote notification when streaming in the live ', async function () {
this.timeout(100000)
const { name, video, ffmpegCommand, streamDate } = await createAndStreamLive(servers[1])
await waitUntilNotification({
server: servers[0],
token: userAccessToken,
notificationType: UserNotificationType.NEW_LIVE_FROM_SUBSCRIPTION,
fromDate: streamDate
})
await checkNewLiveFromSubscription({ ...baseParams, videoName: name, shortUUID: video.shortUUID, checkType: 'presence' })
await stopFfmpeg(ffmpegCommand)
await waitJobs(servers)
})
})
describe('My video is published', function () {
@@ -229,7 +307,7 @@ describe('Test user notifications', function () {
const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 1)
await waitJobs(servers)
await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
await checkMyVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
})
it('Should not send a notification if the wait transcoding is false', async function () {
@@ -250,7 +328,7 @@ describe('Test user notifications', function () {
const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true, fixture: 'video_short_240p.mp4' })
await waitJobs(servers)
await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
await checkMyVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
it('Should send a notification with a transcoded video', async function () {
@@ -259,7 +337,7 @@ describe('Test user notifications', function () {
const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true })
await waitJobs(servers)
await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
await checkMyVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
it('Should send a notification when an imported video is transcoded', async function () {
@@ -277,7 +355,7 @@ describe('Test user notifications', function () {
const { video } = await servers[1].imports.importVideo({ attributes })
await waitJobs(servers)
await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID: video.shortUUID, checkType: 'presence' })
await checkMyVideoIsPublished({ ...baseParams, videoName: name, shortUUID: video.shortUUID, checkType: 'presence' })
})
it('Should send a notification when the scheduled update has been proceeded', async function () {
@@ -296,7 +374,7 @@ describe('Test user notifications', function () {
const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, data)
await wait(6000)
await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
await checkMyVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
it('Should not send a notification before the video is published', async function () {
@@ -314,7 +392,7 @@ describe('Test user notifications', function () {
const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, data)
await wait(6000)
await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
await checkMyVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
})
})
@@ -354,7 +432,7 @@ describe('Test user notifications', function () {
await servers[1].live.waitUntilReplacedByReplay({ videoId: shortUUID })
await waitJobs(servers)
await checkVideoIsPublished({ ...baseParams, videoName: 'non permanent live', shortUUID, checkType: 'presence' })
await checkMyVideoIsPublished({ ...baseParams, videoName: 'non permanent live', shortUUID, checkType: 'presence' })
})
it('Should send a notification is a live replay of a permanent live is published', async function () {
@@ -386,7 +464,7 @@ describe('Test user notifications', function () {
const video = await findExternalSavedVideo(servers[1], liveDetails)
expect(video).to.exist
await checkVideoIsPublished({ ...baseParams, videoName: video.name, shortUUID: video.shortUUID, checkType: 'presence' })
await checkMyVideoIsPublished({ ...baseParams, videoName: video.name, shortUUID: video.shortUUID, checkType: 'presence' })
})
})
@@ -408,7 +486,7 @@ describe('Test user notifications', function () {
const { name, shortUUID, id } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true })
await waitJobs(servers)
await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
await checkMyVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
const tasks: VideoStudioTask[] = [
{

View File

@@ -7,7 +7,8 @@ import {
UserNotification,
UserNotificationSetting,
UserNotificationSettingValue,
UserNotificationType
UserNotificationType,
UserNotificationType_Type
} from '@peertube/peertube-models'
import {
ConfigCommand,
@@ -17,11 +18,13 @@ import {
setAccessTokensToServers,
setDefaultAccountAvatar,
setDefaultChannelAvatar,
setDefaultVideoChannel
setDefaultVideoChannel,
waitJobs
} from '@peertube/peertube-server-commands'
import { expect } from 'chai'
import { inspect } from 'util'
import { MockSmtpServer } from './mock-servers/index.js'
import { wait } from '@peertube/peertube-core-utils'
type CheckerBaseParams = {
server: PeerTubeServer
@@ -55,6 +58,24 @@ function getAllNotificationsSettings (): UserNotificationSetting {
}
}
async function waitUntilNotification (options: {
server: PeerTubeServer
notificationType: UserNotificationType_Type
token: string
fromDate: Date
}) {
const { server, fromDate, notificationType, token } = options
do {
const { data } = await server.notifications.list({ start: 0, count: 5, token })
if (data.some(n => n.type === notificationType && new Date(n.createdAt) >= fromDate)) break
await wait(500)
} while (true)
await waitJobs([ server ])
}
async function checkNewVideoFromSubscription (options: CheckerBaseParams & {
videoName: string
shortUUID: string
@@ -85,7 +106,37 @@ async function checkNewVideoFromSubscription (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
async function checkVideoIsPublished (options: CheckerBaseParams & {
async function checkNewLiveFromSubscription (options: CheckerBaseParams & {
videoName: string
shortUUID: string
checkType: CheckerType
}) {
const { videoName, shortUUID } = options
const notificationType = UserNotificationType.NEW_LIVE_FROM_SUBSCRIPTION
function notificationChecker (notification: UserNotification, checkType: CheckerType) {
if (checkType === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
checkVideo(notification.video, videoName, shortUUID)
checkActor(notification.video.channel)
} else {
expect(notification).to.satisfy((n: UserNotification) => {
return n === undefined || n.type !== UserNotificationType.NEW_LIVE_FROM_SUBSCRIPTION || n.video.name !== videoName
})
}
}
function emailNotificationFinder (email: object) {
const text = email['text']
return text.indexOf(shortUUID) !== -1 && text.indexOf('Your subscription') !== -1
}
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
async function checkMyVideoIsPublished (options: CheckerBaseParams & {
videoName: string
shortUUID: string
checkType: CheckerType
@@ -780,10 +831,13 @@ export {
getAllNotificationsSettings,
waitUntilNotification,
checkMyVideoImportIsFinished,
checkUserRegistered,
checkAutoInstanceFollowing,
checkVideoIsPublished,
checkMyVideoIsPublished,
checkNewLiveFromSubscription,
checkNewVideoFromSubscription,
checkNewActorFollow,
checkNewCommentOnMyVideo,
@@ -841,10 +895,9 @@ async function checkNotification (options: CheckerBaseParams & {
if (check.mail) {
// Last email
const email = emails
.slice()
.reverse()
.find(e => emailNotificationFinder(e))
const email = emails.slice()
.reverse()
.find(e => emailNotificationFinder(e))
if (checkType === 'presence') {
const texts = emails.map(e => e.text)