Wechaty Puppet
The term Puppet
in Wechaty is an Abstract Class for implementing protocol plugins. The plugins are the component that helps Wechaty to control the IMs like WeChat(that's the reason we call it puppet!).
The plugins are named PuppetXXX
, like PuppetPuppeteer is using the google puppeteer to control the WeChat Web API via a chrome browser, PuppetPadLocal is using the Pad Protocol to connect with WeChat Server.
- Puppet Directory: https://github.com/wechaty/wechaty-puppet/wiki/Directory
- Puppet Compatibility Table: https://github.com/wechaty/wechaty-puppet/wiki/Compatibility
- Puppet Development Guide: https://github.com/wechaty/wechaty-puppet/wiki/Development
- Puppet Related Links: https://github.com/wechaty/wechaty-puppet/wiki/Links
- Puppet Documentation: https://wechaty.github.io/wechaty-puppet/typedoc/classes/puppet.html
#
WHAT IS WECHATY PUPPETThe term Puppet
in Wechaty is a name that we had picked up to describe part of our system: Puppet is an Abstract Class for implementing plugins, the plugins are the component that helps Wechaty to control the Wechat, that's the reason we call it puppet
.
Plugins are named PuppetXXX, like PuppetPuppeteer is using the chrome puppeteer to control the WeChat Web API via a chrome browser, PuppetService is using the gRPC protocol to connect with a Protocol Server for controlling an iPad/Windows/whatever program.
For a deeper understanding of the Puppet in Wechaty, you can read its documentation from https://wechaty.github.io/wechaty-puppet/typedoc/classes/puppet.html and source code if you like at https://github.com/wechaty/wechaty-puppet/blob/master/src/puppet.ts
#
Important PuppetsPuppetPuppeteer
A web solution to connect WeChat, Wechaty init implement is by web WeChat, which inject js code into chrome.
PuppetMock
A mock function to connect WeChat, not a real implement, for testing other connectors to connect with Wechaty, in other words: a mock solution to implement puppet. This is used for further to connect other solutions, such as iPad, Xposed, iOs, windows client...
PuppetPadLocal
An iPad solution to connect WeChat
PuppetService
See: </docs/puppet-services/>
#
Using Puppet with Wechaty ExamplesUsing wechaty-puppet-mock to run ding-dong-bot
Using wechaty-puppet-padpro to run ding-dong-bot
#
Basic RulesHere are some rules that a Wechaty Puppet should follow:
- Emit Self Messages: when the bot says anything, the bot should receive a message said by itself. (and the
message.self()
will return true for this message) - Perfect Logout:
logout
method should clean all the user session data from the puppet service, and the status of the App on the phone should display correctly (not log in on any devices). - State-less Session Management (with MemoryCard support): the puppet service should save the user session data to the memory card, and can be restored from the memory card. (See: #16)
- MIME File Name Extension Convention: FileBoxChunk.name must be able to convert to a MIME type and versa visa. The puppet needs to set the name with the right extension (.jpg, .pdf, etc) to the name of the file box. See: https://github.com/wechaty/wechaty-puppet-hostie/discussions/115,
- To be added.
See: https://github.com/wechaty/puppet-services/discussions/54
#
MemoryCardWhen a Wechaty bots logged in, it will have a authorized secret data to store their logged-in session, for example, the device information (62 data for pad protocol), the cookie (if you are using the web protocol), and the user session secrets, etc.
The memory card is a module designed to store those data.
#
Wechaty bot login with memory card module- wechaty start()
- wechaty instanciates memory card (see wechaty.ts:start())
- wechaty set memory card to puppet (see wechaty.ts:initPuppet())
- puppet start()
- puppet load session from memory card
- puppet logged in
- by loaded session, or
- by scan qr code
- puppet save the session secret data to memory card
- memory card will be saved to file or network storage for future reuse
#
ConclusionBy saving the user login session secret data to memory card, the Wechaty system can save the state to local, so that it can make the puppet service provider service stateless.
Current neither of the Donut, WXWork, Rock, PadLocal have not support this stateless feature, nor the Wechaty system are ready for it.
To be implemented for our ecosystem.
See: https://github.com/wechaty/puppet-services/discussions/16
#
Event OrderI think I can contribute some analytics to this problem:
- As the log & puppet testing shows: the
ready
event is after thelogin
event - However, the Wechaty system needs to load the contact payload of the
userSelf
before it emits thelogin
event because the login event of Wechaty needs to take auserSelf
instance, and it needs to beready-ed
.
So there will be some delay before the Wechaty emit the login
event after it received the login
event from its puppet.
Please pay attention to this behavior and let me know if this issue was caused by it.
#
Potential SolutionFor a more robust Wechaty system, we can consider saving the ready
event if the login
event is not emitted in Wechaty.
And when we emit the login
event in Wechaty, we can check if the puppet has already ready-ed
, and if so, it can emit the ready
event right after the login
event.
See: https://github.com/wechaty/puppet-services/issues/31
ready
#
Event: Need to fire ready
event after the bot logined and all data has been synced.
For example, after we re-installed the WeChat app on our phone, it has to load contacts/rooms from the server for a long time.
See: https://github.com/wechaty/wechaty-puppet-service/issues/18
#
NPM Publication-
wechaty-puppet
must not a dependency. It should be put in devDependencies and peerDependencies -
wechaty
must not a dependency. It should be put in devDependencies and peerDependencies - must exist
examples/ding-dong-bot.ts
to implement the ding/dong logic, use puppet api only.
heartbeat
#
Event: Puppet must emit heartbeats for provide a health check signal.
heartbeat
design#
The Here are the details:
- Wechaty Puppet is designed to emit at least one event in 60 seconds. If we do not have any events to emit, then we need to emit a
heartbeat
event so that it can prove itself is alive and healthy. See: https://github.com/wechaty/wechaty-puppet/blob/bab9e29c088c33fa8bc6e148d9bdadbd453fd138/src/puppet.ts#L253-L254 - It seems that the PadLocal does not have any
heartbeat
event to emit when there are no other events, so if your bot idle for more than 60 seconds, then the Wechaty Puppet system will think the puppet provider has dead, so it will callreset
to try to recover the puppet.
A leaking of heartbeat
example logs:
heartbeat
Example#
Here's an example from our puppeteer puppet, which emits heartbeats in the browser, so if the browser dead, we will get to know because the heartbeat will be lost.
See: https://github.com/wechaty/puppet-services/issues/85#issuecomment-769967606
#
Wechaty Puppet Message Processing FlowYes, video
messagge is not supported now, and pr is welcome. I believe this feature is simple for you. You can have a try so you can become a wechaty contributor 👍
Please refer to :
We now support very limit message types:
In order to support receiving more message types, like audio, you need to look at:
Congratulations! It seems that you can receive the right webhook payload from WeChat Official Server when you sent an audio message to your Official Account!
However, it seems that the Wechaty Message Payload has not been set correctly. In order to make it correct, you need to understand the message processing flow in Wechaty Puppet.
#
Wechaty Puppet Message Processing FlowThe Webhook get called by the Tencent Server (what you have done already)
The message event will be propagated from the
Webhook
class to theOfficialAccount
class:The message event will be propagated from the
OfficialAccount
class to thePuppetOA
class:After message event be propagated from the PuppetOA to Wechaty, then the puppet.messagePayload() will be called to get the Wechaty Message Payload. Here is the most important part: we need to construct a Wechaty Message Payload from the Raw Message Payload (source code at here):
#
What to Do NextSo it will be very clear that, what we need to do to support the new Message Type (audio in this case), is to implement the messageRawPayload
methods, which you can find here:
I hope the above explanation could help you to move forward, please feel free to let me know if you have more questions.
See: https://github.com/wechaty/wechaty-puppet-official-account/issues/19
Ding
/Dong
Protocol#
Puppet has a API named ding(data: string): void
, and the Puppet must:
- emit a
dong
event when theding()
method has been called - the payload of the
dong
event might contains adata
key with the value exactly match thedata
when calling theding()
method.
This is for active(passive) health checking, and this is also a workaround for some edge case communication between the top puppet with the bottom puppet.