wechaty / puppet-wechat4u

Wechat4u Puppet for Wechaty
https://www.npmjs.com/package/wechaty-puppet-wechat4u
Apache License 2.0
114 stars 38 forks source link

Failure to retrieve message ID after sending a message, leading to recall failure #82

Open Nimbly8836 opened 5 months ago

Nimbly8836 commented 5 months ago

Failure to retrieve message ID after sending a message, leading to recall failure

When I try to recall a message after sending it, I find that I cannot find the message ID of the sent message anywhere.

My code:

contact.say(text).then((msg) => {
    // this msg is undefined
    if (msg) {
        CacheHelper.getInstances().addUndoMessageCache(
            ctx.message.message_id, msg.id)
    }
    ...
})

The same issue occurs with room:

room.say(text)
    .then(msg => {
         // this msg is undefined
        if (msg) {
            CacheHelper.getInstances().addUndoMessageCache(
                ctx.message.message_id, msg.id)
        }
        ...
    })

My Solution

When I tried to modify it, I successfully retrieved the message ID, but due to my limited understanding of the code and TypeScript, I hope someone can fix this issue.

File puppet-wechat4u.ts:

  override async messageSendText(
    conversationId: string,
    text: string,
  ): Promise<void | string> {
    log.verbose('PuppetWechat4u', 'messageSend(%s, %s)', conversationId, text)

    /**
     * Send a text message, which can contain emojis (😒) and QQ emoticons ([坏笑])
     */
    const res = await this.wechat4u.sendMsg(text, conversationId);

    const msg: WebMessageRawPayload = {
      Content: text,
      CreateTime: Math.floor(Date.now() / 1000),
      FromUserName: this.wechat4u.user.UserName,
      ToUserName: conversationId,
      MsgId: res.MsgID,
      MsgType: WebMessageType.TEXT,
      SubMsgType: WebMessageType.ZERO,
      AppMsgType: WebAppMsgType.TEXT,
      OriginalContent: text, // ?
      Status: "3",
      FileName: "",
      FileSize: 0,
      MMActualContent: "",
      MMActualSender: "",
      MMAppMsgDesc: "",
      MMAppMsgDownloadUrl: "",
      MMAppMsgFileExt: "",
      MMAppMsgFileSize: "",
      MMCategory: [],
      MMDigest: "",
      MMDisplayTime: 0,
      MMFileExt: "",
      MMFileStatus: 0,
      MMImgStyle: "",
      MMLocationDesc: "",
      MMLocationUrl: "",
      MMPeerUserName: "",
      MMPreviewSrc: "",
      MMStatus: 0,
      MMThumbSrc: "",
      MMUploadProgress: 0,
      MediaId: "",
      Signature: "",
      VoiceLength: 0,
      Url: ''
    }

    return await this.sendMessageHandler(msg)
    /**
     * { BaseResponse: { Ret: 0, ErrMsg: '' },
     *  MsgID: '830582407297708303',
     *  LocalID: '15279119663740094' }
     */
  }
  override async messageSendFile(
    conversationId: string,
    file: FileBox,
  ): Promise<void | string> {
    log.verbose('PuppetWechat4u', 'messageSend(%s, %s)', conversationId, file)

    /**
     * Send emoticon through MD5
     */
    // wechat4u.sendMsg({
    //   emoticonMd5: '00c801cdf69127550d93ca52c3f853ff'
    // }, ToUserName)
    //   .catch(err => {
    //     bot.emit('error', err)
    //   })

    /**
     * The following sends images, videos, attachments, etc., by uploading files
     * Common methods are as follows
     * file can be of multiple types
     * filename is required, mainly to determine the file type
     */
    const res = await this.wechat4u.sendMsg({
      file: await file.toStream(),
      filename: file.name,
    }, conversationId);

    let ext
    const extMatch = file.name.match(/.*\.(.*)/)
    if (extMatch && extMatch[1]) {
      ext = extMatch[1].toLowerCase()
    } else {
      ext = ''
    }

    let msgType
    switch (ext) {
      case 'bmp':
      case 'jpeg':
      case 'jpg':
      case 'png':
        msgType = WebAppMsgType.IMG
        break
      case 'mp4':
        msgType = WebAppMsgType.VIDEO
        break
      default:
        msgType = WebAppMsgType.ATTACH
    }

    const msg: WebMessageRawPayload = {
      Content: "",
      CreateTime: Math.floor(Date.now() / 1000),
      FromUserName: this.wechat4u.user.UserName,
      ToUserName: conversationId,
      MsgId: res.MsgID,
      MsgType: msgType,
      SubMsgType: WebMessageType.ZERO,
      AppMsgType: msgType,
      OriginalContent: "", // ?
      Status: "3",
      FileName: file.name,
      FileSize: file.size,
      MMActualContent: "",
      MMActualSender: "",
      MMAppMsgDesc: "",
      MMAppMsgDownloadUrl: "",
      MMAppMsgFileExt: "",
      MMAppMsgFileSize: "",
      MMCategory: [],
      MMDigest: "",
      MMDisplayTime: 0,
      MMFileExt: "",
      MMFileStatus: 0,
      MMImgStyle: "",
      MMLocationDesc: "",
      MMLocationUrl: "",
      MMPeerUserName: "",
      MMPreviewSrc: "",
      MMStatus: 0,
      MMThumbSrc: "",
      MMUploadProgress: 0,
      MediaId: "",
      Signature: "",
      VoiceLength: 0,
      Url: ''
    }
    return this.sendMessageHandler(msg)
  }
  private async sendMessageHandler(msg: WebMessageRawPayload) {
    if (!msg.MsgId) {
      log.warn('PuppetWechat4u', 'sendMessageHandler() wechat4u.on(message) no message id: %s', JSON.stringify(msg))
      throw new Error('no id')
    }
    // If the creation time of the message is earlier than the bot startup time, discard it directly
    if (msg.CreateTime < this.startTime) {
      // log.warn('PuppetWechat4u', 'initHookEvents() wechat4u.on(message) is history message: %s', JSON.stringify(msg))
      return
    }
    this.cacheMessageRawPayload.set(msg.MsgId, msg)
    const event = await parseEvent(this, msg)
    if (event.type === EventType.Message) {
      this.emit('message', {messageId: msg.MsgId})
    }
    return msg.MsgId
  }