Terms&Conditions (#18):
* new settings for instance's terms * new channel option for channel's terms
This commit is contained in:
parent
4b49037f68
commit
45a63eaecd
@ -5,6 +5,7 @@
|
||||
### New features
|
||||
|
||||
* #233: new option to [mute anonymous users](https://livingston.frama.io/peertube-plugin-livechat/fr/documentation/user/streamers/moderation/).
|
||||
* #18: terms & conditions. You can configure terms&conditions on your instance that will be shown to each joining users. Streamers can also add terms&conditions in their channels options.
|
||||
|
||||
## 10.1.2
|
||||
|
||||
|
3
client/@types/global.d.ts
vendored
3
client/@types/global.d.ts
vendored
@ -83,6 +83,8 @@ declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_BOT_NICKNAME: string
|
||||
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FOR_MORE_INFO: string
|
||||
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_MUTE_ANONYMOUS_LABEL: string
|
||||
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_MUTE_ANONYMOUS_DESC: string
|
||||
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_TERMS_LABEL: string
|
||||
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_TERMS_DESC: string
|
||||
|
||||
declare const LOC_VALIDATION_ERROR: string
|
||||
declare const LOC_TOO_MANY_ENTRIES: string
|
||||
@ -93,6 +95,7 @@ declare const LOC_INVALID_VALUE_WRONG_FORMAT: string
|
||||
declare const LOC_INVALID_VALUE_NOT_IN_RANGE: string
|
||||
declare const LOC_INVALID_VALUE_FILE_TOO_BIG: string
|
||||
declare const LOC_INVALID_VALUE_DUPLICATE: string
|
||||
declare const LOC_INVALID_VALUE_TOO_LONG: string
|
||||
|
||||
declare const LOC_CHATROOM_NOT_ACCESSIBLE: string
|
||||
|
||||
|
@ -14,6 +14,7 @@ import { customElement, property, state } from 'lit/decorators.js'
|
||||
import { ptTr } from '../../lib/directives/translation'
|
||||
import { Task } from '@lit/task'
|
||||
import { provide } from '@lit/context'
|
||||
import { channelTermsMaxLength } from 'shared/lib/constants'
|
||||
|
||||
@customElement('livechat-channel-configuration')
|
||||
export class ChannelConfigurationElement extends LivechatElement {
|
||||
@ -51,6 +52,10 @@ export class ChannelConfigurationElement extends LivechatElement {
|
||||
})
|
||||
}
|
||||
|
||||
public termsMaxLength (): number {
|
||||
return channelTermsMaxLength
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the form by reloading data from backend.
|
||||
*/
|
||||
@ -120,7 +125,11 @@ export class ChannelConfigurationElement extends LivechatElement {
|
||||
const validationErrorTypes: ValidationErrorType[] | undefined =
|
||||
this.validationError?.properties[`${propertyName}`] ?? undefined
|
||||
|
||||
// FIXME: this code is duplicated in dymamic table form
|
||||
if (validationErrorTypes && validationErrorTypes.length !== 0) {
|
||||
if (validationErrorTypes.includes(ValidationErrorType.Missing)) {
|
||||
errorMessages.push(html`${ptTr(LOC_INVALID_VALUE_MISSING)}`)
|
||||
}
|
||||
if (validationErrorTypes.includes(ValidationErrorType.WrongType)) {
|
||||
errorMessages.push(html`${ptTr(LOC_INVALID_VALUE_WRONG_TYPE)}`)
|
||||
}
|
||||
@ -130,6 +139,9 @@ export class ChannelConfigurationElement extends LivechatElement {
|
||||
if (validationErrorTypes.includes(ValidationErrorType.NotInRange)) {
|
||||
errorMessages.push(html`${ptTr(LOC_INVALID_VALUE_NOT_IN_RANGE)}`)
|
||||
}
|
||||
if (validationErrorTypes.includes(ValidationErrorType.TooLong)) {
|
||||
errorMessages.push(html`${ptTr(LOC_INVALID_VALUE_TOO_LONG)}`)
|
||||
}
|
||||
|
||||
return html`<div id=${feedbackId} class="invalid-feedback">${errorMessages}</div>`
|
||||
} else {
|
||||
|
@ -128,6 +128,36 @@ export function tplChannelConfiguration (el: ChannelConfigurationElement): Templ
|
||||
|
||||
<form livechat-configuration-channel-options role="form" @submit=${el.saveConfig} @change=${el.resetValidation}>
|
||||
|
||||
<livechat-configuration-section-header
|
||||
.label=${ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_TERMS_LABEL)}
|
||||
.description=${ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_TERMS_DESC, true)}
|
||||
.helpPage=${'documentation/user/streamers/channel'}>
|
||||
</livechat-configuration-section-header>
|
||||
<div class="form-group">
|
||||
<textarea
|
||||
name="terms"
|
||||
id="peertube-livechat-terms"
|
||||
.value=${el.channelConfiguration?.configuration.terms ?? ''}
|
||||
maxlength=${el.termsMaxLength()}
|
||||
class=${classMap(
|
||||
Object.assign(
|
||||
{ 'form-control': true },
|
||||
el.getInputValidationClass('terms')
|
||||
)
|
||||
)}
|
||||
@change=${(event: Event) => {
|
||||
if (event?.target && el.channelConfiguration) {
|
||||
let value: string | undefined = (event.target as HTMLTextAreaElement).value
|
||||
if (value === '') { value = undefined }
|
||||
el.channelConfiguration.configuration.terms = value
|
||||
}
|
||||
el.requestUpdate('channelConfiguration')
|
||||
}
|
||||
}
|
||||
></textarea>
|
||||
${el.renderFeedback('peertube-livechat-terms-feedback', 'terms')}
|
||||
</div>
|
||||
|
||||
<livechat-configuration-section-header
|
||||
.label=${ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_MUTE_ANONYMOUS_LABEL)}
|
||||
.description=${ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_MUTE_ANONYMOUS_DESC, true)}
|
||||
|
@ -11,6 +11,7 @@ import type {
|
||||
import { ValidationError, ValidationErrorType } from '../../lib/models/validation'
|
||||
import { getBaseRoute } from '../../../utils/uri'
|
||||
import { maxEmojisPerChannel } from 'shared/lib/emojis'
|
||||
import { channelTermsMaxLength } from 'shared/lib/constants'
|
||||
|
||||
export class ChannelDetailsService {
|
||||
public _registerClientOptions: RegisterClientOptions
|
||||
@ -27,6 +28,10 @@ export class ChannelDetailsService {
|
||||
validateOptions = async (channelConfigurationOptions: ChannelConfigurationOptions): Promise<boolean> => {
|
||||
const propertiesError: ValidationError['properties'] = {}
|
||||
|
||||
if (channelConfigurationOptions.terms && channelConfigurationOptions.terms.length > channelTermsMaxLength) {
|
||||
propertiesError.terms = [ValidationErrorType.TooLong]
|
||||
}
|
||||
|
||||
const botConf = channelConfigurationOptions.bot
|
||||
const slowModeDuration = channelConfigurationOptions.slowMode.duration
|
||||
|
||||
|
@ -672,6 +672,7 @@ export class DynamicTableFormElement extends LivechatElement {
|
||||
const validationErrorTypes: ValidationErrorType[] | undefined =
|
||||
this.validation?.[`${this.validationPrefix}.${originalIndex}.${propertyName}`]
|
||||
|
||||
// FIXME: this code is duplicated in channel-configuration
|
||||
if (validationErrorTypes !== undefined && validationErrorTypes.length !== 0) {
|
||||
if (validationErrorTypes.includes(ValidationErrorType.Missing)) {
|
||||
errorMessages.push(html`${ptTr(LOC_INVALID_VALUE_MISSING)}`)
|
||||
@ -688,6 +689,9 @@ export class DynamicTableFormElement extends LivechatElement {
|
||||
if (validationErrorTypes.includes(ValidationErrorType.Duplicate)) {
|
||||
errorMessages.push(html`${ptTr(LOC_INVALID_VALUE_DUPLICATE)}`)
|
||||
}
|
||||
if (validationErrorTypes.includes(ValidationErrorType.TooLong)) {
|
||||
errorMessages.push(html`${ptTr(LOC_INVALID_VALUE_TOO_LONG)}`)
|
||||
}
|
||||
|
||||
return html`<div id="${inputId}-feedback" class="invalid-feedback">${errorMessages}</div>`
|
||||
} else {
|
||||
|
@ -7,7 +7,8 @@ export enum ValidationErrorType {
|
||||
WrongType,
|
||||
WrongFormat,
|
||||
NotInRange,
|
||||
Duplicate
|
||||
Duplicate,
|
||||
TooLong
|
||||
}
|
||||
|
||||
export class ValidationError extends Error {
|
||||
|
@ -45,6 +45,11 @@ diagnostic: |
|
||||
|
||||
chat_title: "<h3>Chat</h3>"
|
||||
|
||||
chat_terms_label: "Terms & Conditions"
|
||||
chat_terms_description: |
|
||||
These terms & conditions will be shown to all users when then join chatrooms.
|
||||
Streamers can also configure terms & conditions for their channels, that will be shown right after these global terms & conditions.
|
||||
|
||||
list_rooms_label: "List existing rooms"
|
||||
list_rooms_description: |
|
||||
<a class="peertube-plugin-livechat-prosody-list-rooms-btn">List rooms</a>
|
||||
@ -455,6 +460,7 @@ invalid_value_wrong_format: "Value is in the wrong format."
|
||||
invalid_value_not_in_range: "Value is not in authorized range."
|
||||
invalid_value_file_too_big: "File size is too big (max size: %s)."
|
||||
invalid_value_duplicate: "Duplicate value"
|
||||
invalid_value_too_long: "Value too long"
|
||||
too_many_entries: "Too many entries"
|
||||
|
||||
slow_mode_info: "Slow mode is enabled, users can send a message every %1$s seconds."
|
||||
@ -553,3 +559,6 @@ livechat_configuration_channel_mute_anonymous_desc: |
|
||||
Default value for new chatrooms.
|
||||
For existing chatrooms, you can change the feature in the room configuration form.
|
||||
When this feature is enabled, anonymous users can only read the chat, and not send messages.
|
||||
livechat_configuration_channel_terms_label: "Channel's chat terms & conditions"
|
||||
livechat_configuration_channel_terms_desc: |
|
||||
You can configure a "terms & conditions" message that will be shown to users joining your chatrooms.
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
import type { RegisterServerOptions } from '@peertube/peertube-types'
|
||||
import type { ChannelConfigurationOptions } from '../../../../shared/lib/types'
|
||||
import { channelTermsMaxLength } from '../../../../shared/lib/constants'
|
||||
|
||||
/**
|
||||
* Sanitize data so that they can safely be used/stored for channel configuration configuration.
|
||||
@ -43,6 +44,16 @@ async function sanitizeChannelConfigurationOptions (
|
||||
throw new Error('Invalid data.mute data type')
|
||||
}
|
||||
|
||||
// terms not present in livechat <= 10.2.0
|
||||
let terms = data.terms
|
||||
if (terms !== undefined && (typeof terms !== 'string')) {
|
||||
throw new Error('Invalid data.terms data type')
|
||||
}
|
||||
if (terms && terms.length > channelTermsMaxLength) {
|
||||
throw new Error('data.terms value too long')
|
||||
}
|
||||
if (terms === '') { terms = undefined }
|
||||
|
||||
const result: ChannelConfigurationOptions = {
|
||||
bot: {
|
||||
enabled: _readBoolean(botData, 'enabled'),
|
||||
@ -59,6 +70,9 @@ async function sanitizeChannelConfigurationOptions (
|
||||
anonymous: _readBoolean(mute, 'anonymous')
|
||||
}
|
||||
}
|
||||
if (terms !== undefined) {
|
||||
result.terms = terms
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
@ -52,7 +52,8 @@ function getDefaultChannelConfigurationOptions (_options: RegisterServerOptions)
|
||||
},
|
||||
mute: {
|
||||
anonymous: false
|
||||
}
|
||||
},
|
||||
terms: undefined
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,6 +148,14 @@ function initChatSettings ({ registerSetting }: RegisterServerOptions): void {
|
||||
private: true,
|
||||
descriptionHTML: loc('chat_title')
|
||||
})
|
||||
registerSetting({
|
||||
name: 'chat-terms',
|
||||
private: true,
|
||||
label: loc('chat_terms_label'),
|
||||
type: 'input-textarea',
|
||||
default: '',
|
||||
descriptionHTML: loc('chat_terms_description')
|
||||
})
|
||||
registerSetting({
|
||||
name: 'prosody-list-rooms',
|
||||
label: loc('list_rooms_label'),
|
||||
|
1
shared/lib/constants.ts
Normal file
1
shared/lib/constants.ts
Normal file
@ -0,0 +1 @@
|
||||
export const channelTermsMaxLength = 400
|
@ -101,11 +101,12 @@ interface ChannelConfigurationOptions {
|
||||
slowMode: {
|
||||
duration: number
|
||||
}
|
||||
mute: {
|
||||
mute: { // comes with Livechat 10.2.0
|
||||
anonymous: boolean
|
||||
// TODO: https://github.com/JohnXLivingston/peertube-plugin-livechat/issues/127
|
||||
// nonFollowers: boolean (or a number of seconds?)
|
||||
}
|
||||
terms?: string // comes with Livechat 10.2.0
|
||||
}
|
||||
|
||||
interface ChannelForbiddenWords {
|
||||
|
Loading…
x
Reference in New Issue
Block a user