Chat can be enabled in video properties.
This commit is contained in:
parent
07b7f4d732
commit
385a0074c1
@ -9,11 +9,14 @@
|
||||
### Features
|
||||
|
||||
* 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
|
||||
|
||||
* 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)
|
||||
* New settings
|
||||
* By default, the «activate chat for all lives» is disabled (now that we can enable the webchat per video)
|
||||
|
||||
### 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'
|
||||
descriptionHTML?: string
|
||||
default?: string | boolean
|
||||
private: boolean
|
||||
hidden?: (options: any) => boolean
|
||||
}
|
||||
interface RegisterClientSettingsScript {
|
||||
isSettingHidden: (options: {
|
||||
@ -46,10 +46,18 @@ interface RegisterClientSettingsScript {
|
||||
}) => boolean
|
||||
}
|
||||
|
||||
interface RegisterClientVideoFieldOptions {
|
||||
type: 'update' | 'upload' | 'import-url' | 'import-torrent' | 'go-live'
|
||||
}
|
||||
|
||||
interface RegisterOptions {
|
||||
registerHook: (options: RegisterClientHookOptions) => void
|
||||
peertubeHelpers: RegisterClientHelpers
|
||||
registerSettingsScript: (options: RegisterClientSettingsScript) => void
|
||||
registerVideoField: (
|
||||
commonOptions: RegisterClientFormFieldOptions,
|
||||
videoFormOptions: RegisterClientVideoFieldOptions
|
||||
) => void
|
||||
}
|
||||
|
||||
interface Video {
|
||||
|
@ -23,6 +23,8 @@ function register ({ registerSettingsScript }: RegisterOptions): void {
|
||||
return options.formValues['chat-type'] === 'disabled'
|
||||
case 'chat-only-locals-warning':
|
||||
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
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
function register ({ registerHook }: RegisterOptions): void {
|
||||
async function register ({ peertubeHelpers, registerHook, registerVideoField }: RegisterOptions): Promise<void> {
|
||||
registerHook({
|
||||
target: 'action:router.navigation-end',
|
||||
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 {
|
||||
|
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.
|
||||
id?: number
|
||||
uuid: string
|
||||
name: string
|
||||
category: number
|
||||
@ -81,6 +82,7 @@ interface MVideoThumbnail { // FIXME: this interface is not complete.
|
||||
downloadEnabled: boolean
|
||||
state: VideoState
|
||||
channelId: number
|
||||
pluginData?: any
|
||||
}
|
||||
|
||||
// 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-open-blank',
|
||||
'chat-only-locals',
|
||||
'chat-per-live-video',
|
||||
'chat-all-lives',
|
||||
'chat-all-non-lives',
|
||||
'chat-videos-list'
|
||||
@ -26,6 +27,10 @@ export async function diagVideo (test: string, { settingsManager }: RegisterServ
|
||||
}
|
||||
|
||||
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']) {
|
||||
result.messages.push('Chat is enabled for all lives.')
|
||||
atLeastOne = true
|
||||
|
@ -7,6 +7,7 @@ import { getUserNickname } from '../helpers'
|
||||
import { Affiliations, getVideoAffiliations } from '../prosody/config/affiliations'
|
||||
import { getProsodyDomain } from '../prosody/config/domain'
|
||||
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
|
||||
interface RoomDefaults {
|
||||
@ -45,10 +46,15 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
|
||||
res.sendStatus(403)
|
||||
return
|
||||
}
|
||||
|
||||
// Adding the custom fields:
|
||||
await fillVideoCustomFields(options, video)
|
||||
|
||||
// check settings (chat enabled for this video?)
|
||||
const settings = await options.settingsManager.getSettings([
|
||||
'chat-type',
|
||||
'chat-only-locals',
|
||||
'chat-per-live-video',
|
||||
'chat-all-lives',
|
||||
'chat-all-non-lives',
|
||||
'chat-videos-list'
|
||||
@ -59,9 +65,10 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
|
||||
return
|
||||
}
|
||||
if (!videoHasWebchat({
|
||||
'chat-only-locals': settings['chat-only-locals'] as boolean,
|
||||
'chat-all-lives': settings['chat-all-lives'] as boolean,
|
||||
'chat-all-non-lives': settings['chat-all-non-lives'] as boolean,
|
||||
'chat-only-locals': !!settings['chat-only-locals'],
|
||||
'chat-per-live-video': !!settings['chat-per-live-video'],
|
||||
'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
|
||||
}, video)) {
|
||||
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(
|
||||
async (req: Request, res: Response, _next: NextFunction) => {
|
||||
const settings = await options.settingsManager.getSettings([
|
||||
'chat-type',
|
||||
'chat-only-locals',
|
||||
'chat-all-lives',
|
||||
'chat-all-non-lives',
|
||||
'chat-videos-list'
|
||||
'chat-type'
|
||||
])
|
||||
if (settings['chat-type'] !== ('builtin-prosody' as ChatType)) {
|
||||
logger.warn('Prosody chat is not active')
|
||||
@ -153,11 +156,7 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
|
||||
router.get('/user/user_exists', asyncMiddleware(
|
||||
async (req: Request, res: Response, _next: NextFunction) => {
|
||||
const settings = await options.settingsManager.getSettings([
|
||||
'chat-type',
|
||||
'chat-only-locals',
|
||||
'chat-all-lives',
|
||||
'chat-all-non-lives',
|
||||
'chat-videos-list'
|
||||
'chat-type'
|
||||
])
|
||||
if (settings['chat-type'] !== ('builtin-prosody' as ChatType)) {
|
||||
logger.warn('Prosody chat is not active')
|
||||
|
@ -195,13 +195,31 @@ function initSettings (options: RegisterServerOptions): void {
|
||||
<span class="peertube-plugin-livechat-warning">
|
||||
The plugin is not compatible with video federation yet.
|
||||
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>`
|
||||
})
|
||||
registerSetting({
|
||||
name: 'chat-all-lives',
|
||||
label: 'Activate chat for all lives',
|
||||
type: 'input-checkbox',
|
||||
default: true,
|
||||
default: false,
|
||||
descriptionHTML: 'If checked, the chat will be enabled for all lives.',
|
||||
private: false
|
||||
})
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { migrateSettings } from './lib/migration/settings'
|
||||
import { initSettings } from './lib/settings'
|
||||
import { initCustomFields } from './lib/custom-fields'
|
||||
import { initRouters } from './lib/routers/index'
|
||||
import { ensureProsodyRunning, ensureProsodyNotRunning } from './lib/prosody/ctl'
|
||||
import decache from 'decache'
|
||||
@ -19,6 +20,7 @@ async function register (options: RegisterServerOptions): Promise<any> {
|
||||
await migrateSettings(options)
|
||||
|
||||
await initSettings(options)
|
||||
await initCustomFields(options)
|
||||
await initRouters(options)
|
||||
|
||||
await ensureProsodyRunning(options)
|
||||
|
@ -2,6 +2,7 @@ import { parseConfigUUIDs } from './config'
|
||||
|
||||
interface SharedSettings {
|
||||
'chat-only-locals': boolean
|
||||
'chat-per-live-video': boolean
|
||||
'chat-all-lives': boolean
|
||||
'chat-all-non-lives': boolean
|
||||
'chat-videos-list': string
|
||||
@ -10,6 +11,9 @@ interface SharedSettings {
|
||||
interface SharedVideoBase {
|
||||
uuid: string
|
||||
isLive: boolean
|
||||
pluginData?: {
|
||||
'livechat-active'?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
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 (video.isLive) return true
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user