Configure bot name + refactoring.

This commit is contained in:
John Livingston 2023-09-19 18:56:39 +02:00
parent 9e7d9c6069
commit 4fe972dc10
No known key found for this signature in database
GPG Key ID: B17B5640CE66CDBC
7 changed files with 78 additions and 38 deletions

View File

@ -44,3 +44,4 @@ declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_ENABLE_BOT_LABEL: string
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_BOT_OPTIONS_TITLE: string declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_BOT_OPTIONS_TITLE: string
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL: string declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL: string
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_BANNED_JIDS_LABEL: string declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_BANNED_JIDS_LABEL: string
declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_BOT_NICKNAME: string

View File

@ -27,6 +27,7 @@ async function vivifyConfigurationChannel (
const data = new FormData(form) const data = new FormData(form)
const channelConfigurationOptions: ChannelConfigurationOptions = { const channelConfigurationOptions: ChannelConfigurationOptions = {
bot: data.get('bot') === '1', bot: data.get('bot') === '1',
botNickname: data.get('bot_nickname')?.toString() ?? '',
bannedJIDs: (data.get('banned_jids')?.toString() ?? '').split(/\r?\n|\r|\n/g), bannedJIDs: (data.get('banned_jids')?.toString() ?? '').split(/\r?\n|\r|\n/g),
forbiddenWords: (data.get('forbidden_words')?.toString() ?? '').split(/\r?\n|\r|\n/g) forbiddenWords: (data.get('forbidden_words')?.toString() ?? '').split(/\r?\n|\r|\n/g)
} }

View File

@ -47,6 +47,7 @@ async function renderConfigurationChannel (
bannedJIDs: await peertubeHelpers.translate(LOC_LIVECHAT_CONFIGURATION_CHANNEL_BANNED_JIDS_LABEL), bannedJIDs: await peertubeHelpers.translate(LOC_LIVECHAT_CONFIGURATION_CHANNEL_BANNED_JIDS_LABEL),
save: await peertubeHelpers.translate(LOC_SAVE), save: await peertubeHelpers.translate(LOC_SAVE),
cancel: await peertubeHelpers.translate(LOC_CANCEL), cancel: await peertubeHelpers.translate(LOC_CANCEL),
botNickname: await peertubeHelpers.translate(LOC_LIVECHAT_CONFIGURATION_CHANNEL_BOT_NICKNAME),
channelConfiguration channelConfiguration
} }
@ -69,6 +70,14 @@ async function renderConfigurationChannel (
</fieldset> </fieldset>
<fieldset livechat-configuration-channel-options-bot-enabled> <fieldset livechat-configuration-channel-options-bot-enabled>
<legend>{{botOptions}}</legend> <legend>{{botOptions}}</legend>
<label>
{{botNickname}}
<input
type="text"
name="bot_nickname"
value="{{channelConfiguration.configuration.botNickname}}"
/>
</label>
<label> <label>
{{forbiddenWords}} {{forbiddenWords}}
<textarea name="forbidden_words"> <textarea name="forbidden_words">

View File

@ -317,4 +317,4 @@ livechat_configuration_channel_enable_bot_label: "Enable moderation bot"
livechat_configuration_channel_bot_options_title: "Moderation bot options" livechat_configuration_channel_bot_options_title: "Moderation bot options"
livechat_configuration_channel_forbidden_words_label: "Forbidden words or expressions" livechat_configuration_channel_forbidden_words_label: "Forbidden words or expressions"
livechat_configuration_channel_banned_jids_label: "Banned users and patterns" livechat_configuration_channel_banned_jids_label: "Banned users and patterns"
livechat_configuration_channel_bot_nickname: "Bot nickname"

View File

@ -14,27 +14,51 @@ async function sanitizeChannelConfigurationOptions (
_channelId: number | string, _channelId: number | string,
data: any data: any
): Promise<ChannelConfigurationOptions> { ): Promise<ChannelConfigurationOptions> {
const result = {
bot: false,
bannedJIDs: [],
forbiddenWords: []
}
if (typeof data !== 'object') { if (typeof data !== 'object') {
throw new Error('Invalid data type') throw new Error('Invalid data type')
} }
// boolean fields
for (const f of ['bot']) { const result: ChannelConfigurationOptions = {
if (!(f in data) || (typeof data[f] !== 'boolean')) { bot: _readBoolean(data, 'bot'),
botNickname: _readSimpleInput(data, 'botNickname'),
bannedJIDs: await _readRegExpArray(data, 'bannedJIDs'),
forbiddenWords: await _readRegExpArray(data, 'forbiddenWords')
}
return result
}
function _readBoolean (data: any, f: string): boolean {
if (!(f in data)) {
return false
}
if (typeof data[f] !== 'boolean') {
throw new Error('Invalid data type for field ' + f) throw new Error('Invalid data type for field ' + f)
} }
result[f as keyof ChannelConfigurationOptions] = data[f] return data[f]
}
function _readSimpleInput (data: any, f: string): string {
if (!(f in data)) {
return ''
} }
// value/regexp array fields if (typeof data[f] !== 'string') {
for (const f of ['bannedJIDs', 'forbiddenWords']) {
if (!(f in data) || !Array.isArray(data[f])) {
throw new Error('Invalid data type for field ' + f) throw new Error('Invalid data type for field ' + f)
} }
// Replacing all invalid characters, no need to throw an error..
return (data[f] as string).replace(/[^\p{L}\p{N}\p{Z}_-]$/gu, '')
}
async function _readRegExpArray (data: any, f: string): Promise<string[]> {
// Note: this function can instanciate a lot of RegExp.
// To avoid freezing the server, we make it async, and will validate each regexp in a separate tick.
if (!(f in data)) {
return []
}
if (!Array.isArray(data[f])) {
throw new Error('Invalid data type for field ' + f)
}
const result: string[] = []
for (const v of data[f]) { for (const v of data[f]) {
if (typeof v !== 'string') { if (typeof v !== 'string') {
throw new Error('Invalid data type in a value of field ' + f) throw new Error('Invalid data type in a value of field ' + f)
@ -45,15 +69,16 @@ async function sanitizeChannelConfigurationOptions (
} }
// value must be a valid regexp // value must be a valid regexp
try { try {
async function _validate (): Promise<void> {
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new RegExp(v) new RegExp(v)
}
await _validate()
} catch (_err) { } catch (_err) {
throw new Error('Invalid value in field ' + f) throw new Error('Invalid value in field ' + f)
} }
(result[f as keyof ChannelConfigurationOptions] as string[]).push(v) result.push(v)
} }
}
return result return result
} }

View File

@ -33,6 +33,7 @@ async function getChannelConfigurationOptions (
function getDefaultChannelConfigurationOptions (_options: RegisterServerOptions): ChannelConfigurationOptions { function getDefaultChannelConfigurationOptions (_options: RegisterServerOptions): ChannelConfigurationOptions {
return { return {
bot: false, bot: false,
botNickname: 'Sepia',
bannedJIDs: [], bannedJIDs: [],
forbiddenWords: [] forbiddenWords: []
} }
@ -77,11 +78,13 @@ function channelConfigurationOptionsToBotRoomConf (
options: RegisterServerOptions, options: RegisterServerOptions,
channelConfigurationOptions: ChannelConfigurationOptions channelConfigurationOptions: ChannelConfigurationOptions
): ChannelCommonRoomConf { ): ChannelCommonRoomConf {
const roomConf = { const roomConf: ChannelCommonRoomConf = {
enabled: channelConfigurationOptions.bot, enabled: channelConfigurationOptions.bot,
// TODO: nick
handlers: [] handlers: []
} }
if (channelConfigurationOptions.botNickname && channelConfigurationOptions.botNickname !== '') {
roomConf.nick = channelConfigurationOptions.botNickname
}
return roomConf return roomConf
} }

View File

@ -54,6 +54,7 @@ interface ChannelInfos {
interface ChannelConfigurationOptions { interface ChannelConfigurationOptions {
bot: boolean bot: boolean
botNickname?: string
forbiddenWords: string[] forbiddenWords: string[]
bannedJIDs: string[] bannedJIDs: string[]
} }