use-moderate.ts 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. import { useEffect, useRef, useState } from 'react'
  2. import type { ModerationService } from '@/models/common'
  3. function splitStringByLength(inputString: string, chunkLength: number) {
  4. const resultArray = []
  5. for (let i = 0; i < inputString.length; i += chunkLength)
  6. resultArray.push(inputString.substring(i, i + chunkLength))
  7. return resultArray
  8. }
  9. export const useModerate = (
  10. content: string,
  11. stop: boolean,
  12. moderationService: (text: string) => ReturnType<ModerationService>,
  13. separateLength = 50,
  14. ) => {
  15. const moderatedContentMap = useRef<Map<number, string>>(new Map())
  16. const moderatingIndex = useRef<number[]>([])
  17. const [contentArr, setContentArr] = useState<string[]>([])
  18. const handleModerate = () => {
  19. const stringArr = splitStringByLength(content, separateLength)
  20. const lastIndex = stringArr.length - 1
  21. stringArr.forEach((item, index) => {
  22. if (!(index in moderatingIndex.current) && !moderatedContentMap.current.get(index)) {
  23. if (index === lastIndex && !stop)
  24. return
  25. moderatingIndex.current.push(index)
  26. moderationService(item).then((res) => {
  27. if (res.flagged) {
  28. moderatedContentMap.current.set(index, res.text)
  29. setContentArr([...stringArr.slice(0, index), res.text, ...stringArr.slice(index + 1)])
  30. }
  31. })
  32. }
  33. })
  34. setContentArr(stringArr)
  35. }
  36. useEffect(() => {
  37. if (content)
  38. handleModerate()
  39. }, [content, stop])
  40. return contentArr.map((item, index) => moderatedContentMap.current.get(index) || item).join('')
  41. }