Repository: koishijs/novelai-bot
File: src/config.ts (TypeScript)

Code before:
    }).description('参数设置'),
    Schema.object({
      type: Schema.const('naifu'),
      sampler: sampler.createSchema(sampler.nai),
    }).description('参数设置'),
    Schema.object({
      model: Schema.union(models).description('默认的生成模型。').default('nai'),
      sampler: sampler.createSchema(sampler.nai),
    }).description('参数设置'),
  ] as const),

  Schema.object({
    orient: Schema.union(orients).description('默认的图片方向。').default('portrait'),
    maxSteps: Schema.natural().description('允许的最大迭代步数。').default(0),
    maxResolution: Schema.natural().description('生成图片的最大尺寸。').default(0),
  }),

  PromptConfig,

  Schema.object({
    output: Schema.union([
      Schema.const('minimal').description('只发送图片'),
      Schema.const('default').description('发送图片和关键信息'),
      Schema.const('verbose').description('发送全部信息'),
    ]).description('输出方式。').default('default'),
    maxIteration: Schema.natural().description('允许的最大请求次数 (设置为 1 以禁用同时请求多张图片)。').default(1),
    maxRetryCount: Schema.natural().description('连接失败时最大的重试次数。').default(3),
    requestTimeout: Schema.number().role('time').description('当请求超过这个时间时会中止并提示超时。').default(Time.minute),
    recallTimeout: Schema.number().role('time').description('图片发送后自动撤回的时间 (设置为 0 以禁用此功能)。').default(0),
    maxConcurrency: Schema.number().description('单个频道下的最大并发数量 (设置为 0 以禁用此功能)。').default(0),
  }).description('高级设置'),
]) as Schema<Config>

interface Forbidden {
  pattern: string
  strict: boolean
}

export function parseForbidden(input: string) {
  return input.trim()
    .toLowerCase()
    .replace(/，/g, ',')
    .split(/(?:,\s*|\s*\n\s*)/g)
    .filter(Boolean)
    .map<Forbidden>((pattern: string) => {
      const strict = pattern.endsWith('!')
      if (strict) pattern = pattern.slice(0, -1)
      pattern = pattern.replace(/[^a-z0-9]+/g, ' ').trim()
      return { pattern, strict }
    })
}

Review comment (suggestion):
```suggestion
    maxIteration: Schema.natural().description('允许的最大请求次数。').default(1),
```

Code after:
    }).description('参数设置'),
    Schema.object({
      type: Schema.const('naifu'),
      sampler: sampler.createSchema(sampler.nai),
    }).description('参数设置'),
    Schema.object({
      model: Schema.union(models).description('默认的生成模型。').default('nai'),
      sampler: sampler.createSchema(sampler.nai),
    }).description('参数设置'),
  ] as const),

  Schema.object({
    orient: Schema.union(orients).description('默认的图片方向。').default('portrait'),
    maxSteps: Schema.natural().description('允许的最大迭代步数。').default(0),
    maxResolution: Schema.natural().description('生成图片的最大尺寸。').default(0),
  }),

  PromptConfig,

  Schema.object({
    output: Schema.union([
      Schema.const('minimal').description('只发送图片'),
      Schema.const('default').description('发送图片和关键信息'),
      Schema.const('verbose').description('发送全部信息'),
    ]).description('输出方式。').default('default'),
    maxIteration: Schema.natural().description('允许的最大绘制次数。').default(1),
    maxRetryCount: Schema.natural().description('连接失败时最大的重试次数。').default(3),
    requestTimeout: Schema.number().role('time').description('当请求超过这个时间时会中止并提示超时。').default(Time.minute),
    recallTimeout: Schema.number().role('time').description('图片发送后自动撤回的时间 (设置为 0 以禁用此功能)。').default(0),
    maxConcurrency: Schema.number().description('单个频道下的最大并发数量 (设置为 0 以禁用此功能)。').default(0),
  }).description('高级设置'),
]) as Schema<Config>

interface Forbidden {
  pattern: string
  strict: boolean
}

export function parseForbidden(input: string) {
  return input.trim()
    .toLowerCase()
    .replace(/，/g, ',')
    .split(/(?:,\s*|\s*\n\s*)/g)
    .filter(Boolean)
    .map<Forbidden>((pattern: string) => {
      const strict = pattern.endsWith('!')
      if (strict) pattern = pattern.slice(0, -1)
      pattern = pattern.replace(/[^a-z0-9]+/g, ' ').trim()
      return { pattern, strict }
    })
}