Chat can be enabled in video properties.
This commit is contained in:
parent
07b7f4d732
commit
385a0074c1
@ -9,11 +9,14 @@
|
|||||||
### Features
|
### Features
|
||||||
|
|
||||||
* New simpler settings screen.
|
* New simpler settings screen.
|
||||||
|
* New field in live video form, to activate the webchat per video. There is a setting for enabling this new feature.
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|
||||||
* Removed compatibility with Peertube previous to 3.2.0.
|
* Removed compatibility with Peertube previous to 3.2.0.
|
||||||
* Restoring default values for checkboxes in settings (there was a bug with Peertube previous to 3.2.0)
|
* Restoring default values for checkboxes in settings (there was a bug with Peertube previous to 3.2.0)
|
||||||
|
* New settings
|
||||||
|
* By default, the «activate chat for all lives» is disabled (now that we can enable the webchat per video)
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
|
10
client/@types/peertube.d.ts
vendored
10
client/@types/peertube.d.ts
vendored
@ -37,7 +37,7 @@ interface RegisterClientFormFieldOptions {
|
|||||||
type: 'input' | 'input-checkbox' | 'input-password' | 'input-textarea' | 'markdown-text' | 'markdown-enhanced'
|
type: 'input' | 'input-checkbox' | 'input-password' | 'input-textarea' | 'markdown-text' | 'markdown-enhanced'
|
||||||
descriptionHTML?: string
|
descriptionHTML?: string
|
||||||
default?: string | boolean
|
default?: string | boolean
|
||||||
private: boolean
|
hidden?: (options: any) => boolean
|
||||||
}
|
}
|
||||||
interface RegisterClientSettingsScript {
|
interface RegisterClientSettingsScript {
|
||||||
isSettingHidden: (options: {
|
isSettingHidden: (options: {
|
||||||
@ -46,10 +46,18 @@ interface RegisterClientSettingsScript {
|
|||||||
}) => boolean
|
}) => boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface RegisterClientVideoFieldOptions {
|
||||||
|
type: 'update' | 'upload' | 'import-url' | 'import-torrent' | 'go-live'
|
||||||
|
}
|
||||||
|
|
||||||
interface RegisterOptions {
|
interface RegisterOptions {
|
||||||
registerHook: (options: RegisterClientHookOptions) => void
|
registerHook: (options: RegisterClientHookOptions) => void
|
||||||
peertubeHelpers: RegisterClientHelpers
|
peertubeHelpers: RegisterClientHelpers
|
||||||
registerSettingsScript: (options: RegisterClientSettingsScript) => void
|
registerSettingsScript: (options: RegisterClientSettingsScript) => void
|
||||||
|
registerVideoField: (
|
||||||
|
commonOptions: RegisterClientFormFieldOptions,
|
||||||
|
videoFormOptions: RegisterClientVideoFieldOptions
|
||||||
|
) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Video {
|
interface Video {
|
||||||
|
@ -23,6 +23,8 @@ function register ({ registerSettingsScript }: RegisterOptions): void {
|
|||||||
return options.formValues['chat-type'] === 'disabled'
|
return options.formValues['chat-type'] === 'disabled'
|
||||||
case 'chat-only-locals-warning':
|
case 'chat-only-locals-warning':
|
||||||
return options.formValues['chat-only-locals'] === true
|
return options.formValues['chat-only-locals'] === true
|
||||||
|
case 'chat-per-live-video-warning':
|
||||||
|
return !(options.formValues['chat-all-lives'] === true && options.formValues['chat-per-live-video'] === true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
function register ({ registerHook }: RegisterOptions): void {
|
async function register ({ peertubeHelpers, registerHook, registerVideoField }: RegisterOptions): Promise<void> {
|
||||||
registerHook({
|
registerHook({
|
||||||
target: 'action:router.navigation-end',
|
target: 'action:router.navigation-end',
|
||||||
handler: () => {
|
handler: () => {
|
||||||
@ -9,6 +9,34 @@ function register ({ registerHook }: RegisterOptions): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const [label, description, settings] = await Promise.all([
|
||||||
|
peertubeHelpers.translate('Use chat'),
|
||||||
|
peertubeHelpers.translate('If enabled, there will be a chat next to the video.'),
|
||||||
|
peertubeHelpers.getSettings()
|
||||||
|
])
|
||||||
|
const webchatFieldOptions: RegisterClientFormFieldOptions = {
|
||||||
|
name: 'livechat-active',
|
||||||
|
label: label,
|
||||||
|
descriptionHTML: description,
|
||||||
|
type: 'input-checkbox',
|
||||||
|
default: true,
|
||||||
|
hidden: ({ liveVideo }) => {
|
||||||
|
if (!liveVideo) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (!settings['chat-per-live-video']) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (settings['chat-all-lives']) {
|
||||||
|
// No need to add this field if live is active for all live videos
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
registerVideoField(webchatFieldOptions, { type: 'update' })
|
||||||
|
registerVideoField(webchatFieldOptions, { type: 'go-live' })
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
2
server/@types/peertube.d.ts
vendored
2
server/@types/peertube.d.ts
vendored
@ -61,6 +61,7 @@ enum VideoState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface MVideoThumbnail { // FIXME: this interface is not complete.
|
interface MVideoThumbnail { // FIXME: this interface is not complete.
|
||||||
|
id?: number
|
||||||
uuid: string
|
uuid: string
|
||||||
name: string
|
name: string
|
||||||
category: number
|
category: number
|
||||||
@ -81,6 +82,7 @@ interface MVideoThumbnail { // FIXME: this interface is not complete.
|
|||||||
downloadEnabled: boolean
|
downloadEnabled: boolean
|
||||||
state: VideoState
|
state: VideoState
|
||||||
channelId: number
|
channelId: number
|
||||||
|
pluginData?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the order
|
// Keep the order
|
||||||
|
63
server/lib/custom-fields.ts
Normal file
63
server/lib/custom-fields.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
async function initCustomFields (options: RegisterServerOptions): Promise<void> {
|
||||||
|
const registerHook = options.registerHook
|
||||||
|
const storageManager = options.storageManager
|
||||||
|
const logger = options.peertubeHelpers.logger
|
||||||
|
|
||||||
|
registerHook({
|
||||||
|
target: 'action:api.video.updated',
|
||||||
|
handler: async (params: any) => {
|
||||||
|
logger.debug('Saving a video, checking for custom fields')
|
||||||
|
|
||||||
|
const body: any = params.body
|
||||||
|
const video: MVideoThumbnail | undefined = params.video
|
||||||
|
if (!video || !video.id) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!body.pluginData) return
|
||||||
|
const value = body.pluginData['livechat-active']
|
||||||
|
// NB: on Peertube 3.2.1, value is "true", "false", or "null", as strings.
|
||||||
|
if (value === true || value === 'true') {
|
||||||
|
logger.info(`Saving livechat-active=true for video ${video.id}`)
|
||||||
|
await storageManager.storeData(`livechat-active-${video.id}`, true)
|
||||||
|
} else if (value === false || value === 'false' || value === 'null') {
|
||||||
|
logger.info(`Saving livechat-active=false for video ${video.id}`)
|
||||||
|
await storageManager.storeData(`livechat-active-${video.id}`, false)
|
||||||
|
} else {
|
||||||
|
logger.error('Unknown value ' + JSON.stringify(value) + ' for livechat-active field.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
registerHook({
|
||||||
|
target: 'filter:api.video.get.result',
|
||||||
|
handler: async (video: MVideoThumbnail): Promise<MVideoThumbnail> => {
|
||||||
|
logger.debug('Getting a video, searching for custom fields')
|
||||||
|
await fillVideoCustomFields(options, video)
|
||||||
|
return video
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fillVideoCustomFields (options: RegisterServerOptions, video: MVideoThumbnail): Promise<void> {
|
||||||
|
if (!video) return video
|
||||||
|
if (!video.pluginData) video.pluginData = {}
|
||||||
|
if (!video.id) return
|
||||||
|
const storageManager = options.storageManager
|
||||||
|
const logger = options.peertubeHelpers.logger
|
||||||
|
|
||||||
|
if (video.isLive) {
|
||||||
|
const result: any = await storageManager.getData(`livechat-active-${video.id}`)
|
||||||
|
logger.debug(`Video ${video.id} has livechat-active=` + JSON.stringify(result))
|
||||||
|
// NB: I got weird stuff here. Maybe Peertube 3.2.1 bug?
|
||||||
|
if (result === true || result === 'true') {
|
||||||
|
video.pluginData['livechat-active'] = true
|
||||||
|
} else if (result === false || result === 'false' || result === 'null') {
|
||||||
|
video.pluginData['livechat-active'] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
initCustomFields,
|
||||||
|
fillVideoCustomFields
|
||||||
|
}
|
@ -7,6 +7,7 @@ export async function diagVideo (test: string, { settingsManager }: RegisterServ
|
|||||||
'chat-auto-display',
|
'chat-auto-display',
|
||||||
'chat-open-blank',
|
'chat-open-blank',
|
||||||
'chat-only-locals',
|
'chat-only-locals',
|
||||||
|
'chat-per-live-video',
|
||||||
'chat-all-lives',
|
'chat-all-lives',
|
||||||
'chat-all-non-lives',
|
'chat-all-non-lives',
|
||||||
'chat-videos-list'
|
'chat-videos-list'
|
||||||
@ -26,6 +27,10 @@ export async function diagVideo (test: string, { settingsManager }: RegisterServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
let atLeastOne: boolean = false
|
let atLeastOne: boolean = false
|
||||||
|
if (videoSettings['chat-per-live-video']) {
|
||||||
|
result.messages.push('Chat can be enabled on live videos.')
|
||||||
|
atLeastOne = true
|
||||||
|
}
|
||||||
if (videoSettings['chat-all-lives']) {
|
if (videoSettings['chat-all-lives']) {
|
||||||
result.messages.push('Chat is enabled for all lives.')
|
result.messages.push('Chat is enabled for all lives.')
|
||||||
atLeastOne = true
|
atLeastOne = true
|
||||||
|
@ -7,6 +7,7 @@ import { getUserNickname } from '../helpers'
|
|||||||
import { Affiliations, getVideoAffiliations } from '../prosody/config/affiliations'
|
import { Affiliations, getVideoAffiliations } from '../prosody/config/affiliations'
|
||||||
import { getProsodyDomain } from '../prosody/config/domain'
|
import { getProsodyDomain } from '../prosody/config/domain'
|
||||||
import type { ChatType } from '../../../shared/lib/types'
|
import type { ChatType } from '../../../shared/lib/types'
|
||||||
|
import { fillVideoCustomFields } from '../custom-fields'
|
||||||
|
|
||||||
// See here for description: https://modules.prosody.im/mod_muc_http_defaults.html
|
// See here for description: https://modules.prosody.im/mod_muc_http_defaults.html
|
||||||
interface RoomDefaults {
|
interface RoomDefaults {
|
||||||
@ -45,10 +46,15 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
|
|||||||
res.sendStatus(403)
|
res.sendStatus(403)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adding the custom fields:
|
||||||
|
await fillVideoCustomFields(options, video)
|
||||||
|
|
||||||
// check settings (chat enabled for this video?)
|
// check settings (chat enabled for this video?)
|
||||||
const settings = await options.settingsManager.getSettings([
|
const settings = await options.settingsManager.getSettings([
|
||||||
'chat-type',
|
'chat-type',
|
||||||
'chat-only-locals',
|
'chat-only-locals',
|
||||||
|
'chat-per-live-video',
|
||||||
'chat-all-lives',
|
'chat-all-lives',
|
||||||
'chat-all-non-lives',
|
'chat-all-non-lives',
|
||||||
'chat-videos-list'
|
'chat-videos-list'
|
||||||
@ -59,9 +65,10 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!videoHasWebchat({
|
if (!videoHasWebchat({
|
||||||
'chat-only-locals': settings['chat-only-locals'] as boolean,
|
'chat-only-locals': !!settings['chat-only-locals'],
|
||||||
'chat-all-lives': settings['chat-all-lives'] as boolean,
|
'chat-per-live-video': !!settings['chat-per-live-video'],
|
||||||
'chat-all-non-lives': settings['chat-all-non-lives'] as boolean,
|
'chat-all-lives': !!settings['chat-all-lives'],
|
||||||
|
'chat-all-non-lives': !!settings['chat-all-non-lives'],
|
||||||
'chat-videos-list': settings['chat-videos-list'] as string
|
'chat-videos-list': settings['chat-videos-list'] as string
|
||||||
}, video)) {
|
}, video)) {
|
||||||
logger.warn(`Video ${jid} has not chat activated`)
|
logger.warn(`Video ${jid} has not chat activated`)
|
||||||
@ -122,11 +129,7 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
|
|||||||
router.get('/user/check_password', asyncMiddleware(
|
router.get('/user/check_password', asyncMiddleware(
|
||||||
async (req: Request, res: Response, _next: NextFunction) => {
|
async (req: Request, res: Response, _next: NextFunction) => {
|
||||||
const settings = await options.settingsManager.getSettings([
|
const settings = await options.settingsManager.getSettings([
|
||||||
'chat-type',
|
'chat-type'
|
||||||
'chat-only-locals',
|
|
||||||
'chat-all-lives',
|
|
||||||
'chat-all-non-lives',
|
|
||||||
'chat-videos-list'
|
|
||||||
])
|
])
|
||||||
if (settings['chat-type'] !== ('builtin-prosody' as ChatType)) {
|
if (settings['chat-type'] !== ('builtin-prosody' as ChatType)) {
|
||||||
logger.warn('Prosody chat is not active')
|
logger.warn('Prosody chat is not active')
|
||||||
@ -153,11 +156,7 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
|
|||||||
router.get('/user/user_exists', asyncMiddleware(
|
router.get('/user/user_exists', asyncMiddleware(
|
||||||
async (req: Request, res: Response, _next: NextFunction) => {
|
async (req: Request, res: Response, _next: NextFunction) => {
|
||||||
const settings = await options.settingsManager.getSettings([
|
const settings = await options.settingsManager.getSettings([
|
||||||
'chat-type',
|
'chat-type'
|
||||||
'chat-only-locals',
|
|
||||||
'chat-all-lives',
|
|
||||||
'chat-all-non-lives',
|
|
||||||
'chat-videos-list'
|
|
||||||
])
|
])
|
||||||
if (settings['chat-type'] !== ('builtin-prosody' as ChatType)) {
|
if (settings['chat-type'] !== ('builtin-prosody' as ChatType)) {
|
||||||
logger.warn('Prosody chat is not active')
|
logger.warn('Prosody chat is not active')
|
||||||
|
@ -195,13 +195,31 @@ function initSettings (options: RegisterServerOptions): void {
|
|||||||
<span class="peertube-plugin-livechat-warning">
|
<span class="peertube-plugin-livechat-warning">
|
||||||
The plugin is not compatible with video federation yet.
|
The plugin is not compatible with video federation yet.
|
||||||
The webchat will only be accessible for people watching videos on your server.
|
The webchat will only be accessible for people watching videos on your server.
|
||||||
|
</span>`
|
||||||
|
})
|
||||||
|
registerSetting({
|
||||||
|
name: 'chat-per-live-video',
|
||||||
|
label: 'Users can activate the chat for their lives',
|
||||||
|
type: 'input-checkbox',
|
||||||
|
default: true,
|
||||||
|
descriptionHTML: 'If checked, all live videos will have a checkbox in there properties for enabling the webchat.',
|
||||||
|
private: false
|
||||||
|
})
|
||||||
|
registerSetting({
|
||||||
|
name: 'chat-per-live-video-warning',
|
||||||
|
type: 'html',
|
||||||
|
private: true,
|
||||||
|
descriptionHTML: `
|
||||||
|
<span class="peertube-plugin-livechat-warning">
|
||||||
|
You have enabled the setting «Users can activate the chat for their lives».
|
||||||
|
It is redundant with the «Activate chat for all lives» setting.
|
||||||
</span>`
|
</span>`
|
||||||
})
|
})
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: 'chat-all-lives',
|
name: 'chat-all-lives',
|
||||||
label: 'Activate chat for all lives',
|
label: 'Activate chat for all lives',
|
||||||
type: 'input-checkbox',
|
type: 'input-checkbox',
|
||||||
default: true,
|
default: false,
|
||||||
descriptionHTML: 'If checked, the chat will be enabled for all lives.',
|
descriptionHTML: 'If checked, the chat will be enabled for all lives.',
|
||||||
private: false
|
private: false
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { migrateSettings } from './lib/migration/settings'
|
import { migrateSettings } from './lib/migration/settings'
|
||||||
import { initSettings } from './lib/settings'
|
import { initSettings } from './lib/settings'
|
||||||
|
import { initCustomFields } from './lib/custom-fields'
|
||||||
import { initRouters } from './lib/routers/index'
|
import { initRouters } from './lib/routers/index'
|
||||||
import { ensureProsodyRunning, ensureProsodyNotRunning } from './lib/prosody/ctl'
|
import { ensureProsodyRunning, ensureProsodyNotRunning } from './lib/prosody/ctl'
|
||||||
import decache from 'decache'
|
import decache from 'decache'
|
||||||
@ -19,6 +20,7 @@ async function register (options: RegisterServerOptions): Promise<any> {
|
|||||||
await migrateSettings(options)
|
await migrateSettings(options)
|
||||||
|
|
||||||
await initSettings(options)
|
await initSettings(options)
|
||||||
|
await initCustomFields(options)
|
||||||
await initRouters(options)
|
await initRouters(options)
|
||||||
|
|
||||||
await ensureProsodyRunning(options)
|
await ensureProsodyRunning(options)
|
||||||
|
@ -2,6 +2,7 @@ import { parseConfigUUIDs } from './config'
|
|||||||
|
|
||||||
interface SharedSettings {
|
interface SharedSettings {
|
||||||
'chat-only-locals': boolean
|
'chat-only-locals': boolean
|
||||||
|
'chat-per-live-video': boolean
|
||||||
'chat-all-lives': boolean
|
'chat-all-lives': boolean
|
||||||
'chat-all-non-lives': boolean
|
'chat-all-non-lives': boolean
|
||||||
'chat-videos-list': string
|
'chat-videos-list': string
|
||||||
@ -10,6 +11,9 @@ interface SharedSettings {
|
|||||||
interface SharedVideoBase {
|
interface SharedVideoBase {
|
||||||
uuid: string
|
uuid: string
|
||||||
isLive: boolean
|
isLive: boolean
|
||||||
|
pluginData?: {
|
||||||
|
'livechat-active'?: boolean
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SharedVideoFrontend extends SharedVideoBase {
|
interface SharedVideoFrontend extends SharedVideoBase {
|
||||||
@ -31,6 +35,10 @@ function videoHasWebchat (settings: SharedSettings, video: SharedVideo): boolean
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings['chat-per-live-video'] && video.isLive && video.pluginData && video.pluginData['livechat-active']) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if (settings['chat-all-lives']) {
|
if (settings['chat-all-lives']) {
|
||||||
if (video.isLive) return true
|
if (video.isLive) return true
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user