1
1
mirror of https://github.com/leon-ai/leon.git synced 2024-09-11 10:25:40 +03:00

refactor(server): string helper from singleton to static

This commit is contained in:
louistiti 2022-09-26 00:44:40 +08:00
parent 1a4e09f908
commit 9065d713e9
No known key found for this signature in database
GPG Key ID: 7ECA3DD523793FE6
12 changed files with 54 additions and 52 deletions

View File

@ -5,7 +5,7 @@ import { prompt } from 'inquirer'
import path from 'path'
import { LOG } from '@/helpers/log'
import { STRING } from '@/helpers/string'
import { StringHelper } from '@/helpers/string-helper'
dotenv.config()
@ -19,7 +19,7 @@ const generateHttpApiKey = () =>
try {
const shasum = crypto.createHash('sha1')
const str = STRING.random(11)
const str = StringHelper.random(11)
const dotEnvPath = path.join(process.cwd(), '.env')
const envVarKey = 'LEON_HTTP_API_KEY'
let content = fs.readFileSync(dotEnvPath, 'utf8')

View File

@ -3,7 +3,7 @@ import fs from 'fs'
import { composeFromPattern } from '@nlpjs/utils'
import { LOG } from '@/helpers/log'
import { STRING } from '@/helpers/string'
import { StringHelper } from '@/helpers/string-helper'
import { SKILL_DOMAIN } from '@/helpers/skill-domain'
/**
@ -111,7 +111,7 @@ export default (lang, nlp) =>
for (let l = 0; l < answers?.length; l += 1) {
const variableKeys = Object.keys(variablesObj)
if (variableKeys.length > 0) {
answers[l] = STRING.findAndMap(answers[l], variablesObj)
answers[l] = StringHelper.findAndMap(answers[l], variablesObj)
}
nlp.addAnswer(lang, `${skillName}.${actionName}`, answers[l])

View File

@ -5,7 +5,7 @@ import { spawn } from 'child_process'
import { langs } from '@@/core/langs.json'
import { HAS_TTS } from '@/constants'
import { LOG } from '@/helpers/log'
import { STRING } from '@/helpers/string'
import { StringHelper } from '@/helpers/string-helper'
import { LANG } from '@/helpers/lang'
import { SKILL_DOMAIN } from '@/helpers/skill-domain'
import Synchronizer from '@/core/synchronizer'
@ -129,7 +129,7 @@ class Brain {
// Parse sentence's value(s) and replace with the given object
if (typeof obj !== 'undefined' && Object.keys(obj).length > 0) {
answer = STRING.findAndMap(answer, obj)
answer = StringHelper.findAndMap(answer, obj)
}
return answer
@ -146,7 +146,7 @@ class Brain {
}
return new Promise(async (resolve, reject) => {
const utteranceId = `${Date.now()}-${STRING.random(4)}`
const utteranceId = `${Date.now()}-${StringHelper.random(4)}`
const intentObjectPath = path.join(
__dirname,
`../tmp/${utteranceId}.json`
@ -450,7 +450,7 @@ class Brain {
*/
if (utteranceHasEntities && answer.indexOf('{{') !== -1) {
obj.currentEntities.forEach((entityObj) => {
answer = STRING.findAndMap(answer, {
answer = StringHelper.findAndMap(answer, {
[`{{ ${entityObj.entity} }}`]: entityObj.resolution.value
})
@ -469,7 +469,7 @@ class Brain {
const valuesArr =
entities[entity].options[entityObj.option].data[dataKey]
answer = STRING.findAndMap(answer, {
answer = StringHelper.findAndMap(answer, {
[match]:
valuesArr[Math.floor(Math.random() * valuesArr.length)]
})

View File

@ -3,7 +3,7 @@ import path from 'path'
import archiver from 'archiver'
import { LOG } from '@/helpers/log'
import { STRING } from '@/helpers/string'
import { StringHelper } from '@/helpers/string-helper'
const getDownloads = async (fastify, options) => {
fastify.get(`/api/${options.apiVersion}/downloads`, (request, reply) => {
@ -28,12 +28,12 @@ const getDownloads = async (fastify, options) => {
const skill = path.join(dlDomainDir, `${request.query.skill}.py`)
LOG.info(
`Checking existence of the ${STRING.ucFirst(
`Checking existence of the ${StringHelper.ucFirst(
request.query.skill
)} skill...`
)
if (fs.existsSync(skill)) {
LOG.success(`${STRING.ucFirst(request.query.skill)} skill exists`)
LOG.success(`${StringHelper.ucFirst(request.query.skill)} skill exists`)
const downloadsDir = `${dlDomainDir}/${request.query.skill}`
LOG.info('Reading downloads directory...')

View File

@ -6,7 +6,7 @@
import fs from 'fs'
import { LOG } from '@/helpers/log'
import { STRING } from '@/helpers/string'
import { StringHelper } from '@/helpers/string-helper'
class Ner {
constructor(ner) {
@ -34,7 +34,7 @@ class Ner {
const { classification } = obj
// Remove end-punctuation and add an end-whitespace
const utterance = `${STRING.removeEndPunctuation(obj.utterance)} `
const utterance = `${StringHelper.removeEndPunctuation(obj.utterance)} `
const { actions } = JSON.parse(
fs.readFileSync(utteranceSamplesFilePath, 'utf8')
)
@ -116,7 +116,7 @@ class Ner {
return new Promise((resolve) => {
for (let j = 0; j < entity.conditions.length; j += 1) {
const condition = entity.conditions[j]
const conditionMethod = `add${STRING.snakeToPascalCase(
const conditionMethod = `add${StringHelper.snakeToPascalCase(
condition.type
)}Condition`

View File

@ -18,7 +18,7 @@ import {
} from '@/constants'
import Ner from '@/core/ner'
import { LOG } from '@/helpers/log'
import { STRING } from '@/helpers/string'
import { StringHelper } from '@/helpers/string-helper'
import { LANG } from '@/helpers/lang'
import TcpClient from '@/core/tcp-client'
import Conversation from '@/core/conversation'
@ -270,7 +270,7 @@ class Nlu {
const spacyEntity = {
[entity]: {
options: {
[resolution.value]: [STRING.ucFirst(resolution.value)]
[resolution.value]: [StringHelper.ucFirst(resolution.value)]
}
}
}

View File

@ -1,19 +1,11 @@
class StringHelper {
private static instance: StringHelper
constructor() {
if (StringHelper.instance == null) {
StringHelper.instance = this
}
}
export class StringHelper {
/**
* Parse, map (with object) and replace value(s) in a string
* @param toReplace The string containing the placeholders to replace
* @param obj The object containing the value(s) to replace with
* @example findAndMap('Hello %name%!', { '%name%': 'Louis' }) // Hello Louis!
*/
public findAndMap(toReplace: string, obj: Record<string, unknown>) {
public static findAndMap(toReplace: string, obj: Record<string, unknown>) {
return toReplace.replace(
new RegExp(Object.keys(obj).join('|'), 'gi'),
(matched) => obj[matched] as string
@ -25,7 +17,7 @@ class StringHelper {
* @param str String to transform
* @example ucFirst('hello world') // Hello world
*/
public ucFirst(str: string) {
public static ucFirst(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
@ -34,7 +26,7 @@ class StringHelper {
* @param str String to transform
* @example snakeToPascalCase('hello_world') // HelloWorld
*/
public snakeToPascalCase(str: string) {
public static snakeToPascalCase(str: string) {
return str
.split('_')
.map((chunk) => this.ucFirst(chunk))
@ -46,7 +38,7 @@ class StringHelper {
* @param length Length of the string
* @example random(6) // 4f3a2b
*/
public random(length: number) {
public static random(length: number) {
return Math.random().toString(36).slice(-length)
}
@ -55,7 +47,7 @@ class StringHelper {
* @param str String to remove accents
* @example removeAccents('éèà') // eea
*/
public removeAccents(str: string) {
public static removeAccents(str: string) {
return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
}
@ -64,7 +56,7 @@ class StringHelper {
* @param str String to remove punctuation
* @example removeEndPunctuation('Hello world!') // Hello world
*/
public removeEndPunctuation(str: string) {
public static removeEndPunctuation(str: string) {
const punctuations = ['.', ';', ':', '?', '!']
const lastChar = str.charAt(str.length - 1)
@ -75,5 +67,3 @@ class StringHelper {
return str
}
}
export const STRING = new StringHelper()

View File

@ -6,7 +6,7 @@ import fs from 'fs'
import path from 'path'
import { LOG } from '@/helpers/log'
import { STRING } from '@/helpers/string'
import { StringHelper } from '@/helpers/string-helper'
LOG.title('Amazon Polly Synthesizer')
@ -51,7 +51,9 @@ synthesizer.init = (lang) => {
* Save string to audio file
*/
synthesizer.save = (speech, em, cb) => {
const file = `${__dirname}/../../tmp/${Date.now()}-${STRING.random(4)}.mp3`
const file = `${__dirname}/../../tmp/${Date.now()}-${StringHelper.random(
4
)}.mp3`
synthesizer.conf.Text = speech

View File

@ -5,7 +5,7 @@ import { path as ffprobePath } from '@ffprobe-installer/ffprobe'
import fs from 'fs'
import { LOG } from '@/helpers/log'
import { STRING } from '@/helpers/string'
import { StringHelper } from '@/helpers/string-helper'
LOG.title('Flite Synthesizer')
@ -48,7 +48,9 @@ synthesizer.init = (lang) => {
* Save string to audio file
*/
synthesizer.save = (speech, em, cb) => {
const file = `${__dirname}/../../tmp/${Date.now()}-${STRING.random(4)}.wav`
const file = `${__dirname}/../../tmp/${Date.now()}-${StringHelper.random(
4
)}.wav`
const process = spawn('bin/flite/flite', [
speech,
'--setf',

View File

@ -6,7 +6,7 @@ import fs from 'fs'
import path from 'path'
import { LOG } from '@/helpers/log'
import { STRING } from '@/helpers/string'
import { StringHelper } from '@/helpers/string-helper'
LOG.title('Google Cloud TTS Synthesizer')
@ -57,7 +57,9 @@ synthesizer.init = (lang) => {
* Save string to audio file
*/
synthesizer.save = (speech, em, cb) => {
const file = `${__dirname}/../../tmp/${Date.now()}-${STRING.random(4)}.mp3`
const file = `${__dirname}/../../tmp/${Date.now()}-${StringHelper.random(
4
)}.mp3`
synthesizer.conf.input = { text: speech }

View File

@ -7,7 +7,7 @@ import fs from 'fs'
import path from 'path'
import { LOG } from '@/helpers/log'
import { STRING } from '@/helpers/string'
import { StringHelper } from '@/helpers/string-helper'
LOG.title('Watson TTS Synthesizer')
@ -55,7 +55,9 @@ synthesizer.init = (lang) => {
* Save string to audio file
*/
synthesizer.save = (speech, em, cb) => {
const file = `${__dirname}/../../tmp/${Date.now()}-${STRING.random(4)}.wav`
const file = `${__dirname}/../../tmp/${Date.now()}-${StringHelper.random(
4
)}.wav`
synthesizer.conf.text = speech

View File

@ -1,9 +1,9 @@
import string from '@/helpers/string'
import string from '@/helpers/string-helper'
describe('string helper', () => {
describe('pnr()', () => {
test('replaces substring to a string defined in an object', () => {
expect(string.pnr('Hello %name%', { '%name%': 'Leon' })).toBe(
expect(StringHelper.pnr('Hello %name%', { '%name%': 'Leon' })).toBe(
'Hello Leon'
)
})
@ -11,20 +11,20 @@ describe('string helper', () => {
describe('ucfirst()', () => {
test('transforms first letter to uppercase', () => {
expect(string.ucfirst('leon')).toBe('Leon')
expect(StringHelper.ucfirst('leon')).toBe('Leon')
})
})
describe('snakeToPascalCase()', () => {
test('transforms snake_case string to PascalCase', () => {
expect(string.snakeToPascalCase('leon')).toBe('Leon')
expect(string.snakeToPascalCase('this_is_leon')).toBe('ThisIsLeon')
expect(StringHelper.snakeToPascalCase('leon')).toBe('Leon')
expect(StringHelper.snakeToPascalCase('this_is_leon')).toBe('ThisIsLeon')
})
})
describe('random()', () => {
test('generates a random string with a length defined by a given number', () => {
const s = string.random(6)
const s = StringHelper.random(6)
expect(typeof s).toBe('string')
expect(s.length).toBe(6)
})
@ -32,18 +32,22 @@ describe('string helper', () => {
describe('removeAccents()', () => {
test('removes accents', () => {
expect(string.removeAccents('àâèéêëîïôöûüùÛÜç')).toBe('aaeeeeiioouuuUUc')
expect(StringHelper.removeAccents('àâèéêëîïôöûüùÛÜç')).toBe(
'aaeeeeiioouuuUUc'
)
})
})
describe('removeEndPunctuation()', () => {
test('removes end-punctuation', () => {
expect(string.removeEndPunctuation('Who are you?')).toBe('Who are you')
expect(string.removeEndPunctuation('This is great.')).toBe(
expect(StringHelper.removeEndPunctuation('Who are you?')).toBe(
'Who are you'
)
expect(StringHelper.removeEndPunctuation('This is great.')).toBe(
'This is great'
)
expect(
string.removeEndPunctuation('This string has no punctuation')
StringHelper.removeEndPunctuation('This string has no punctuation')
).toBe('This string has no punctuation')
})
})