wechaty / puppet-wechat

Wechaty Puppet Provider for WeChat
https://www.npmjs.com/package/wechaty-puppet-wechat
Apache License 2.0
409 stars 68 forks source link

Recalled type of messages do not trigger .on('message') again #31

Open huan opened 6 years ago

huan commented 6 years ago

Moved from https://github.com/Chatie/wechaty/issues/1065 author @WiseClock

Provide Your Network Information

  1. Where is the location of your server? (i.e. City, or In/Out China) Canada
  2. Which cloud platform(AliYun/Qcloud/DigitalOcean/etc) are you using? Own PC

Run npm run doctor or wechaty run doctor(for docker user), paste output here

npm ERR! missing script: doctor

Expected behavior

Recalling messages trigger the .on('message') method with a message of type RECALLED and the original message wrapped in.

It should be fixed months ago in: https://github.com/Chatie/wechaty/commit/174b6775c4e9242e5f003094b2f9e10953c978f2 Am I missing something in the setup or is the API changed?

Actual behavior

Recalling a message does not trigger the .on('message') method and shows nothing in the console output.

Steps to reproduce the behavior (and fixes, if any)

  1. Write a .on('message') method to log the message into console.
  2. Send a message to the bot, and it'll show in console
  3. Recall the message sent, nothing will show up in console

Full Output Logs

Show Logs ### Paste the full output logs here with `WECHATY_LOG=silly` set ```shell D:\CODE\node\rin_wechaty>set WECHATY_LOG=silly D:\CODE\node\rin_wechaty>node index.js WECHATY_LOG=silly 22:50:24 SILL Brolog WECHATY_LOG set level to silly 22:50:24 INFO Config registering process.on("unhandledRejection") for development/debug 22:50:24 VERB Config constructor() 22:50:25 SILL StateSwitch constructor(Wechaty) 22:50:25 VERB Wechaty contructor() 22:50:25 VERB Profile constructor(rin) 22:50:25 VERB Wechaty on(scan, function) registered 22:50:25 VERB Wechaty onFunction(scan) 22:50:25 VERB Wechaty on(login, function) registered 22:50:25 VERB Wechaty onFunction(login) 22:50:25 VERB Wechaty on(message, function) registered 22:50:25 VERB Wechaty onFunction(message) 22:50:25 SILL Wechaty version() form development environment is not availble: ENOENT: no such file o r directory, stat 'D:\CODE\node\rin_wechaty\node_modules\wechaty\dist\.git' 22:50:25 INFO Wechaty v0.13.42 starting... 22:50:25 VERB Wechaty puppet: web 22:50:25 VERB Wechaty profile: rin 22:50:25 VERB Wechaty uuid: 2adc06ea-47a2-4bee-8769-88953859c350 22:50:25 SILL StateSwitch on() is false 22:50:25 SILL StateSwitch on() is false 22:50:25 SILL StateSwitch on() is false 22:50:25 VERB StateSwitch on(pending) <- (false) 22:50:25 VERB Profile load() file: D:\CODE\node\rin_wechaty\rin.wechaty.json 22:50:25 VERB Wechaty initPuppet() 22:50:25 SILL StateSwitch constructor(Puppet) 22:50:25 VERB Wechaty initPuppet() puppet.on(error) registered 22:50:25 VERB Wechaty initPuppet() puppet.on(friend) registered 22:50:25 VERB Wechaty initPuppet() puppet.on(heartbeat) registered 22:50:25 VERB Wechaty initPuppet() puppet.on(login) registered 22:50:25 VERB Wechaty initPuppet() puppet.on(logout) registered 22:50:25 VERB Wechaty initPuppet() puppet.on(message) registered 22:50:25 VERB Wechaty initPuppet() puppet.on(room-join) registered 22:50:25 VERB Wechaty initPuppet() puppet.on(room-leave) registered 22:50:25 VERB Wechaty initPuppet() puppet.on(room-topic) registered 22:50:25 VERB Wechaty initPuppet() puppet.on(scan) registered 22:50:25 VERB Config puppetInstance(PuppetWeb) 22:50:25 VERB PuppetWeb init() with Profile 22:50:25 SILL StateSwitch on() is false 22:50:25 VERB StateSwitch on(pending) <- (false) 22:50:25 VERB PuppetWeb initWatchdogForPuppet() 22:50:25 VERB PuppetWeb initWatchdogForScan() 22:50:25 VERB PuppetWeb initBridge() 22:50:25 SILL StateSwitch off() is false 22:50:25 VERB PuppetWebBridge constructor() 22:50:25 SILL StateSwitch constructor(PuppetWebBridge) 22:50:25 VERB PuppetWebBridge init() 22:50:25 SILL StateSwitch on() is false 22:50:25 VERB StateSwitch on(pending) <- (false) 22:50:25 VERB PuppetWebBridge initBrowser() 22:50:27 VERB PUppetWebBridge initBrowser() version: HeadlessChrome/65.0.3312.0 22:50:27 VERB PuppetWebBridge init() initBrowser() done 22:50:27 VERB PuppetWebBridge initPage() 22:50:28 VERB Profile get(cookies) 22:50:28 VERB PuppetWebBridge cookieDomain([object Object],[object Object],[object Object],[object O bject],[object Object],[object Object],[object Object],[object Object],[object Object],[object Objec t],[object Object],[object Object]) 22:50:28 SILL PuppetWebBridge cookieDomain() got https://web.wechat.com 22:50:28 VERB PuppetWebBridge initPage() before page.goto(url) 22:50:32 VERB PuppetWebBridge initPage() after page.goto(url) 22:50:32 SILL PuppetWebBridge initPage() page.setCookie() 12 cookies set back 22:50:32 VERB PuppetWebBridge initPage() on(load) https://web.wechat.com/ 22:50:32 SILL StateSwitch off() is false 22:50:33 VERB PuppetWebBridge readyAngular() 22:50:33 VERB PuppetWebBridge inject() 22:50:33 SILL PuppetWebBridge inject() eval(Wechaty) return code[200] message[WechatyBro Inject Done ] 22:50:33 SILL PuppetWebBridge proxyWechaty(init) 22:50:33 SILL PuppetWebEvent onLog(login(page refresh)) 22:50:33 VERB PuppetWebEvent onLogin(page refresh, 30) 22:50:33 SILL StateSwitch off() is false 22:50:33 VERB PuppetWebBridge getUserName() 22:50:33 SILL PuppetWebBridge proxyWechaty(getUserName) 22:50:33 SILL PuppetWebEvent onLog(init() scanCode: null) 22:50:33 SILL PuppetWebEvent onDing(heartbeat@browser) 22:50:33 SILL PuppetWeb initWatchdogForPuppet() dog.on(feed, food={type=undefined, data=heartbeat@br owser}) 22:50:33 SILL PuppetWebEvent onLog(inited!. ;-D) 22:50:33 VERB PuppetWebEvent onLogin() browser not fully loaded(ttl=30), retry later 22:50:33 SILL PuppetWebBridge evaluate() 22:50:33 SILL PuppetWebBridge inject() Wechaty.init() return code[200] message[WechatyBro Init Succ] 22:50:33 VERB PuppetWebBridge ding(ding() OK!) 22:50:33 SILL PuppetWebBridge proxyWechaty(ding , ding() OK!) 22:50:33 SILL PuppetWebEvent onLogin() innerHTML:
seanxlliu commented 5 years ago

I hit the same issue, and took a day to investigate. This should be a regression due to the puppet refactoring.

There are two issues need to be resolved:

  1. a crash on 'wechaty-bro.js' due to the factory instance not passed in as this. it can be fixed by this code oldRecalledMsgProcess.call(chatFactory, msg) I can help to submit a fix.

  2. A design change needs to be discussed before it can be fixed. When a recalled message is hooked, the 'message' event is trigger only with the message id as here, the messagePayload is called to load the message payload from cache, which causes the original 'RECALLED' type (10002) is lost. There are two solutions but they may all slightly effect the whole 'puppet' design, and I am not sure how it effects other types of puppet implementations,

    a. trigger the 'message' event with additional parameters/metadata, so the message type can be changed by this information after the message is loaded. b. trigger a new 'recall' event with the cached message.

@huan I would like to contribute the fix after we discuss the design. suggestions?

seanxlliu commented 5 years ago

Submitted a PR for the first issue.

huan commented 5 years ago

@seanxlliu Thank you very much for taking the time to investigate this issue!

I totally agree with you with your analysis, and you did a great PR to fix this.

About the topic 2, after I thinking about your plan A and plan B, I have a new idea that the RECALLED action needs a pseudo message to help us to understand what was happening in the message event.

Which means I have a plan C as the following:

C. when a message was recalled, we:

  1. get the message id from the message that had been recalled. let's say, the id is id_real_message_be_recalled
  2. generate a message id for a new RECALL message, let's say, the id is id_pseudo_recall_message
  3. create a message payload for id_presudo_recall_message, set the MessageType to RECALL, and save the recalled message id id_real_message_be_recalled to this payload(for a dirty example, we save the id in the text property)
  4. emit(id_pseudo_recall_message)

With this design, I believe there's no need to modify any puppet design, and we can easily deal with the RECALLED message in the on('message') event.

Please free free to let me know what you think, and you are welcome to implement it with a new PR!

seanxlliu commented 5 years ago

Agree. Will work on that.