fix: 修复一处循环引用
This commit is contained in:
		
							parent
							
								
									61b099ce81
								
							
						
					
					
						commit
						f665dcf634
					
				| 
						 | 
					@ -20,11 +20,17 @@ import ListenerLoader from './core/events.loader.js'
 | 
				
			||||||
 * 扩展
 | 
					 * 扩展
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
import { Client, segment } from 'icqq'
 | 
					import { Client, segment } from 'icqq'
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
import { plugin } from './core/plugins/index.js'
 | 
					import { plugin } from './core/plugins/index.js'
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * global
 | 
					 * global.plugin
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
global.plugin = plugin
 | 
					global.plugin = plugin
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * global.segment
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
global.segment = segment
 | 
					global.segment = segment
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,4 @@
 | 
				
			||||||
import fs from 'fs'
 | 
					import { execAsync, readJSON } from '../utils/index.js'
 | 
				
			||||||
import { exec } from 'child_process'
 | 
					 | 
				
			||||||
import { join } from 'path'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 校验运行
 | 
					 * 校验运行
 | 
				
			||||||
| 
						 | 
					@ -11,14 +9,18 @@ export async function checkRun() {
 | 
				
			||||||
   * 
 | 
					   * 
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  if (process.argv[1].includes('pm2')) return
 | 
					  if (process.argv[1].includes('pm2')) return
 | 
				
			||||||
  if (process.argv[1].includes('test')) return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * 
 | 
					   * 
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  const cfg = pm2Cfg()
 | 
					  if (process.argv[1].includes('test')) return
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  const cfg = readJSON('./config/pm2/pm2.json')
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
  if (!cfg) return
 | 
					  if (!cfg) return
 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * 
 | 
					   * 
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
| 
						 | 
					@ -31,38 +33,5 @@ export async function checkRun() {
 | 
				
			||||||
      logger.mark('已停止后台进程,防止重复运行')
 | 
					      logger.mark('已停止后台进程,防止重复运行')
 | 
				
			||||||
      execAsync(`pm2 stop ${cfg.apps[0].name}`).catch(logger.error)
 | 
					      execAsync(`pm2 stop ${cfg.apps[0].name}`).catch(logger.error)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  }).catch(() => { })
 | 
				
			||||||
 | 
					 | 
				
			||||||
  }).catch(()=>{})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * @param cmd 
 | 
					 | 
				
			||||||
 * @returns 
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function execAsync(cmd: string): Promise<{
 | 
					 | 
				
			||||||
  stdout: string,
 | 
					 | 
				
			||||||
  stderr: string
 | 
					 | 
				
			||||||
}> {
 | 
					 | 
				
			||||||
  return new Promise((resolve, reject) => {
 | 
					 | 
				
			||||||
    exec(cmd, (error, stdout, stderr) => {
 | 
					 | 
				
			||||||
      if (error) reject(error)
 | 
					 | 
				
			||||||
      resolve({ stdout, stderr })
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * @returns 
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function pm2Cfg() {
 | 
					 | 
				
			||||||
  try {
 | 
					 | 
				
			||||||
    const cfg = fs.readFileSync(join(process.cwd(), './config/pm2/pm2.json'), 'utf-8')
 | 
					 | 
				
			||||||
    return JSON.parse(cfg)
 | 
					 | 
				
			||||||
  } catch {
 | 
					 | 
				
			||||||
    return false
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
import YAML from 'yaml'
 | 
					import YAML from 'yaml'
 | 
				
			||||||
import fs from 'node:fs'
 | 
					 | 
				
			||||||
import chokidar from 'chokidar'
 | 
					import chokidar from 'chokidar'
 | 
				
			||||||
import { join } from 'node:path'
 | 
					import { join } from 'node:path'
 | 
				
			||||||
 | 
					import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync } from 'node:fs'
 | 
				
			||||||
import { CONFIG_DEFAULT_PATH, CONFIG_INIT_PATH } from './system.js'
 | 
					import { CONFIG_DEFAULT_PATH, CONFIG_INIT_PATH } from './system.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -35,14 +35,14 @@ class Cfg {
 | 
				
			||||||
  initCfg() {
 | 
					  initCfg() {
 | 
				
			||||||
    const path = CONFIG_INIT_PATH
 | 
					    const path = CONFIG_INIT_PATH
 | 
				
			||||||
    const pathDef = CONFIG_DEFAULT_PATH
 | 
					    const pathDef = CONFIG_DEFAULT_PATH
 | 
				
			||||||
    const files = fs.readdirSync(pathDef).filter(file => file.endsWith('.yaml'))
 | 
					    const files = readdirSync(pathDef).filter(file => file.endsWith('.yaml'))
 | 
				
			||||||
    for (let file of files) {
 | 
					    for (let file of files) {
 | 
				
			||||||
      if (!fs.existsSync(`${path}${file}`)) {
 | 
					      if (!existsSync(`${path}${file}`)) {
 | 
				
			||||||
        fs.copyFileSync(`${pathDef}${file}`, `${path}${file}`)
 | 
					        copyFileSync(`${pathDef}${file}`, `${path}${file}`)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!fs.existsSync("data")) fs.mkdirSync("data")
 | 
					    if (!existsSync("data")) mkdirSync("data")
 | 
				
			||||||
    if (!fs.existsSync("resources")) fs.mkdirSync("resources")
 | 
					    if (!existsSync("resources")) mkdirSync("resources")
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
| 
						 | 
					@ -124,7 +124,7 @@ class Cfg {
 | 
				
			||||||
  get package() {
 | 
					  get package() {
 | 
				
			||||||
    if (this._package) return this._package
 | 
					    if (this._package) return this._package
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const data = fs.readFileSync('package.json', 'utf8')
 | 
					      const data = readFileSync('package.json', 'utf8')
 | 
				
			||||||
      this._package = JSON.parse(data)
 | 
					      this._package = JSON.parse(data)
 | 
				
			||||||
      return this._package
 | 
					      return this._package
 | 
				
			||||||
    } catch {
 | 
					    } catch {
 | 
				
			||||||
| 
						 | 
					@ -195,7 +195,7 @@ class Cfg {
 | 
				
			||||||
    if (this.config[key]) return this.config[key]
 | 
					    if (this.config[key]) return this.config[key]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.config[key] = YAML.parse(
 | 
					    this.config[key] = YAML.parse(
 | 
				
			||||||
      fs.readFileSync(file, 'utf8')
 | 
					      readFileSync(file, 'utf8')
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.watch(file, name, type)
 | 
					    this.watch(file, name, type)
 | 
				
			||||||
| 
						 | 
					@ -210,7 +210,7 @@ class Cfg {
 | 
				
			||||||
   * @param type 
 | 
					   * @param type 
 | 
				
			||||||
   * @returns 
 | 
					   * @returns 
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  watch(file:string, name:string, type = 'default_config') {
 | 
					  watch(file: string, name: string, type = 'default_config') {
 | 
				
			||||||
    const key = `${type}.${name}`
 | 
					    const key = `${type}.${name}`
 | 
				
			||||||
    if (this.watcher[key]) return
 | 
					    if (this.watcher[key]) return
 | 
				
			||||||
    const watcher = chokidar.watch(file)
 | 
					    const watcher = chokidar.watch(file)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,28 @@
 | 
				
			||||||
export { checkRun } from './check.js'
 | 
					
 | 
				
			||||||
import config from './config.js'
 | 
					import config from './config.js'
 | 
				
			||||||
export { checkInit, UpdateTitle as checkUpdateTitle } from './init.js'
 | 
					 | 
				
			||||||
export const ConfigController = config
 | 
					 | 
				
			||||||
import QQ from './qq.js'
 | 
					 | 
				
			||||||
export const createQQ = QQ
 | 
					 | 
				
			||||||
import RedisInit from './redis.js'
 | 
					import RedisInit from './redis.js'
 | 
				
			||||||
 | 
					import QQ from './qq.js'
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export { checkRun } from './check.js'
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export { checkInit, UpdateTitle as checkUpdateTitle } from './init.js'
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 配置控制器
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const ConfigController = config
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 创建qq配置
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const createQQ = QQ
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 初始化redis全局对象
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export const redisInit = RedisInit
 | 
					export const redisInit = RedisInit
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export * from './system.js'
 | 
					export * from './system.js'
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@ export default async function createQQ() {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * 
 | 
					   * 
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  let propmtList = [
 | 
					  const propmtList = [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      type: 'Input',
 | 
					      type: 'Input',
 | 
				
			||||||
      message: '请输入机器人QQ号(建议用小号):',
 | 
					      message: '请输入机器人QQ号(建议用小号):',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,8 +10,9 @@ export default async function redisInit() {
 | 
				
			||||||
  const rc = cfg.redis
 | 
					  const rc = cfg.redis
 | 
				
			||||||
  const redisUn = rc.username || ""
 | 
					  const redisUn = rc.username || ""
 | 
				
			||||||
  let redisPw = rc.password ? `:${rc.password}` : ""
 | 
					  let redisPw = rc.password ? `:${rc.password}` : ""
 | 
				
			||||||
  if (rc.username || rc.password)
 | 
					  if (rc.username || rc.password) {
 | 
				
			||||||
    redisPw += "@"
 | 
					    redisPw += "@"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  const redisUrl = `redis://${redisUn}${redisPw}${rc.host}:${rc.port}/${rc.db}`
 | 
					  const redisUrl = `redis://${redisUn}${redisPw}${rc.host}:${rc.port}/${rc.db}`
 | 
				
			||||||
  let client = createClient({ url: redisUrl })
 | 
					  let client = createClient({ url: redisUrl })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,9 +58,7 @@ export default async function redisInit() {
 | 
				
			||||||
 * @returns 
 | 
					 * @returns 
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
async function aarch64() {
 | 
					async function aarch64() {
 | 
				
			||||||
  if (process.platform == "win32") {
 | 
					  if (process.platform == "win32") return ""
 | 
				
			||||||
    return ""
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return await execAsync("uname -m").then(async arch => {
 | 
					  return await execAsync("uname -m").then(async arch => {
 | 
				
			||||||
    if (arch.stdout && arch.stdout.includes("aarch64")) {
 | 
					    if (arch.stdout && arch.stdout.includes("aarch64")) {
 | 
				
			||||||
      /** 判断redis版本 */
 | 
					      /** 判断redis版本 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,5 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { segment } from 'icqq'
 | 
				
			||||||
import { Common } from '../../miao.js'
 | 
					import { Common } from '../../miao.js'
 | 
				
			||||||
import { EventType } from './types.js'
 | 
					import { EventType } from './types.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +20,9 @@ export class plugin {
 | 
				
			||||||
   * @deprecated 已废弃
 | 
					   * @deprecated 已废弃
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  task = null
 | 
					  task = null
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
  rule: {
 | 
					  rule: {
 | 
				
			||||||
    reg?: RegExp | string
 | 
					    reg?: RegExp | string
 | 
				
			||||||
    fnc: string
 | 
					    fnc: string
 | 
				
			||||||
| 
						 | 
					@ -25,11 +30,30 @@ export class plugin {
 | 
				
			||||||
    log?: boolean
 | 
					    log?: boolean
 | 
				
			||||||
    permission?: string
 | 
					    permission?: string
 | 
				
			||||||
  }[] = []
 | 
					  }[] = []
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
  event = 'message'
 | 
					  event = 'message'
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
  priority = 9999
 | 
					  priority = 9999
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
  namespace = null
 | 
					  namespace = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
  handler = null
 | 
					  handler = null
 | 
				
			||||||
  e: EventType
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  e: EventType & {
 | 
				
			||||||
 | 
					    segment: typeof segment
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @param name 插件名称
 | 
					   * @param name 插件名称
 | 
				
			||||||
| 
						 | 
					@ -103,6 +127,10 @@ export class plugin {
 | 
				
			||||||
      this.handler = handler
 | 
					      this.handler = handler
 | 
				
			||||||
      this.namespace = namespace || ''
 | 
					      this.namespace = namespace || ''
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 携带segment
 | 
				
			||||||
 | 
					    this.e.segment = segment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
import { randomRange } from './mysApi.js'
 | 
					import { randomRange } from '../utils/index.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 整合接口用于查询数据
 | 
					 * 整合接口用于查询数据
 | 
				
			||||||
 * 方便后续用于解耦
 | 
					 * 方便后续用于解耦
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,4 +15,16 @@ export { BaseModel, DailyCache, MysUser, MysUtil, NoteUser }
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @deprecated 已废弃
 | 
					 * @deprecated 已废弃
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export { apiTool, gsCfg, mysApi, mysInfo }
 | 
					export { apiTool }
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @deprecated 已废弃
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export { gsCfg }
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @deprecated 已废弃
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export { mysApi }
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @deprecated 已废弃
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export { mysInfo }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -342,17 +342,3 @@ export default class MysApi {
 | 
				
			||||||
    return result
 | 
					    return result
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @returns
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export function randomRange() {
 | 
					 | 
				
			||||||
  let randomStr = ''
 | 
					 | 
				
			||||||
  let charStr = 'abcdef0123456789'
 | 
					 | 
				
			||||||
  for (let i = 0; i < 64; i++) {
 | 
					 | 
				
			||||||
    let index = Math.round(Math.random() * (charStr.length - 1))
 | 
					 | 
				
			||||||
    randomStr += charStr.substring(index, index + 1)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return randomStr
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ import fetch from 'node-fetch'
 | 
				
			||||||
import fs from 'node:fs'
 | 
					import fs from 'node:fs'
 | 
				
			||||||
import path from 'node:path'
 | 
					import path from 'node:path'
 | 
				
			||||||
import { exec } from 'child_process'
 | 
					import { exec } from 'child_process'
 | 
				
			||||||
 | 
					import { join } from 'path'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 休眠函数
 | 
					 * 休眠函数
 | 
				
			||||||
| 
						 | 
					@ -66,3 +67,31 @@ export function execAsync(cmd: string): Promise<{
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param dir
 | 
				
			||||||
 | 
					 * @returns
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function readJSON(dir: string) {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    const cfg = fs.readFileSync(join(process.cwd(), dir), 'utf-8')
 | 
				
			||||||
 | 
					    return JSON.parse(cfg)
 | 
				
			||||||
 | 
					  } catch {
 | 
				
			||||||
 | 
					    return false
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @returns
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function randomRange() {
 | 
				
			||||||
 | 
					  let randomStr = ''
 | 
				
			||||||
 | 
					  let charStr = 'abcdef0123456789'
 | 
				
			||||||
 | 
					  for (let i = 0; i < 64; i++) {
 | 
				
			||||||
 | 
					    let index = Math.round(Math.random() * (charStr.length - 1))
 | 
				
			||||||
 | 
					    randomStr += charStr.substring(index, index + 1)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return randomStr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue