基于 5G 平台开发 puppet 模块接入 wechaty
- 项目名称:基于5G消息的 Wechaty Puppet 模块的设计与实现
- 学生:鲍耀龙
- 导师:苏畅
- 项目介绍:https://github.com/juzibot/intern/issues/1
- 代码地址:https://github.com/wechaty/puppet-walnut
背景介绍
- Wechaty 社区目前已经支持微信、Whatsapp、企业微信、飞书等常见流行即时通讯工具,并且能够通过多语言 SDK (比如 Python Wechaty) 进行调用。
- 5G Chatbot (RCS) 是近期中国电信运营商基于 5G 的消息战略落地平台,未来的 5G 手机将会内置 RCS 消息的处理能力。
- 硬核桃社区 的 电信运营商商5G Chatbot 平台。
目标计划
- 基于 5G 平台的开放 api 进行封装,实现可以收发消息的机器人 bot。
- 丰富机器人的扩展性功能,完善对于 Wechaty 的 api 适配。
项目进展
- 基于 5G 平台的开放 api 进行封装,实现简单的
ding-dong-bot
。 - 丰富 5G 的消息模式,实现支持富文本、文件、css等多样消息格式的 puppet。
需求分析与设计
1. Wechaty
与Puppet
的交互
- 开发者通过
Wechaty
提供的 Api 来进行具体的交互操作。 Wechaty
只需要具体调用开发者指定的Puppet
即此处的Walnut
来实现开发者需要的逻辑。- 我们的
Walnut
继承于抽象的Puppet
父类,实现其预定义的抽象方法来实现具体的能力。 - 具体的
Walnut
会和5G
平台进行数据交互从而实现真正的 ChatBot。
2. 抽象方法的实现
在继承了抽象父类之后,我们就可以按照自己需要去实现具体的方法。
-
messageMixin: 消息相关的抽象方法
abstract messageContact (messageId: string) : Promise<string> abstract messageFile (messageId: string) : Promise<FileBoxInterface> abstract messageImage (messageId: string, imageType: ImageType) : Promise<FileBoxInterface> abstract messageMiniProgram (messageId: string) : Promise<MiniProgramPayload> abstract messageUrl (messageId: string) : Promise<UrlLinkPayload> abstract messageLocation (messageId: string) : Promise<LocationPayload> abstract messageForward (conversationId: string, messageId: string,) : Promise<void | string> abstract messageSendContact (conversationId: string, contactId: string) : Promise<void | string> abstract messageSendFile (conversationId: string, file: FileBoxInterface) : Promise<void | string> abstract messageSendMiniProgram (conversationId: string, miniProgramPayload: MiniProgramPayload) : Promise<void | string> abstract messageSendText (conversationId: string, text: string, mentionIdList?: string[]) : Promise<void | string> abstract messageSendUrl (conversationId: string, urlLinkPayload: UrlLinkPayload) : Promise<void | string> abstract messageSendLocation (conversationId: string, locationPayload: LocationPayload) : Promise<void | string> abstract messageRecall (messageId: string) : Promise<boolean>
-
contactMixin: 联系人相关的抽象方法
abstract contactSelfName (name: string) : Promise<void> abstract contactSelfQRCode () : Promise<string /* QR Code Value */> abstract contactSelfSignature (signature: string) : Promise<void> abstract contactAlias (contactId: string) : Promise<string> abstract contactAlias (contactId: string, alias: string | null) : Promise<void> abstract contactAvatar (contactId: string) : Promise<FileBoxInterface> abstract contactAvatar (contactId: string, file: FileBoxInterface) : Promise<void> abstract contactPhone (contactId: string, phoneList: string[]) : Promise<void> abstract contactCorporationRemark (contactId: string, corporationRemark: string | null): Promise<void> abstract contactDescription (contactId: string, description: string | null): Promise<void> abstract contactList (): Promise<string[]> abstract contactRawPayload (contactId: string): Promise<any> abstract contactRawPayloadParser (rawPayload: any) : Promise<ContactPayload>
3. 缓存模块
-
当我们的 sever 监听到有用户发送消息,此时我们就需要去对消息的具体内容做一个缓存。
这里我们需要自己实现一个缓存模块,将 message 的具体内容存储进去,并且返回 id。
推荐李卓桓老师开发的缓存组件:flash-store。 https://github.com/huan/flash-store
-
然后我们用 Puppet 触发一个 message 事件,把我们本地缓存的 id 传出去。
this.emit('message', { messageId: messageId })
-
这时候 Wechaty 已经拿到我们消息的 id ,这个时候会根据一个需要我们实现的查询方法来获取本地缓存。
override async messageRawPayload (messageId: string): Promise<WalnutMessagePayload | undefined> { log.verbose('PuppetWalnut', 'messageRawPayload(%s)', messageId) // 这里根据 id 去缓存中查出来刚刚存入的消息 }
-
当查出具体的消息内容后,其实和我们 Wechaty 中预定义的消息结构可能不太一致,需要我们进行一个转换。
override async messageRawPayloadParser (rawPayload: WalnutMessagePayload): Promise<PUPPET.payloads.Message> { // 这里实现转换规则:WalnutMessagePayload ===> PUPPET.payloads.Message }
-
不过这里要注意,在每次进行收发消息的时候 Wechaty 都会去加载一遍我们的联系人缓存。 所以对应的联系人缓存的模块也需要实现:
- contactRawPayloa
- contactRawPayloadParser
项目成果
1. Contact Api 支持
-
Properties
Name Type Description Support Details id string
Get Contact id. This function is depending on the Puppet Implementation, see puppet-compatible-table ✅ Phone number -
Instance Methods
Instance Methods Return type Support Details say(text Or Contact Or File) Promise
✅ ⚠Contact not Support name() String
✅ Phone number alias(newAlias) Promise
✅ friend() Boolean or null
✅ True type() ContactType.Unknown or ContactType.Personal or ContactType.Official
✅ ContactType.Personal gender() ContactGender.Unknown or ContactGender.Male or ContactGender.Female
✅ ContactGender.Unknown province() String or null
❌ city() String or null
❌ avatar() Promise
✅ Default avatar sync() Promise
✅ self() Boolean
✅ Default avatar 👉 https://raw.githubusercontent.com/wechaty/puppet-walnut/main/docs/images/avatar.webp
-
Static Methods
Static Methods Return Type Support Detail find(query) Promise <Contact | null>
✅ findAll(Query Arguements) Promise <Contact []>
✅
2. Message Api 支持
-
Instance Methods
Instance methods Return type Support Detail from() Contact
ornull
✅ to() Contact
ornull
✅ room() Room
ornull
✅ null text() string
✅ say(text Or Contact Or File) Promise
✅ ⚠Contact not Support type() MessageType
✅ Message.Text self() boolean
✅ mention() Promise
❌ mentionSelf() Promise
❌ forward(to) Promise
✅ date() Date
✅ age() Number
✅ toFileBox() Promise
✅ toContact() Promise
✅ toUrlLink() Promise
✅ -
Static Method
Static Methods Return type Support Detail find() Promise
✅ findAll() Promise
✅
3. 消息格式支持
消息类型 | 从属(根据接口返回) | 获取方式 | 接收 | 发送 | 群聊 |
---|---|---|---|---|---|
文本 | text |
message.text |
✅ | ✅ | ❌ |
图片 | image |
message.toImage() |
✅ | ✅ | ❌ |
视频 | video |
message.toFilebox() |
✅ | ❌ | ❌ |
音频 | audio |
message.toFilebox() |
✅ | ❌ | ❌ |
位置 | location |
message.toLocation() |
❌ | ❌ | ❌ |
文件 | other |
message.toFilebox() |
✅ | ❌ | ❌ |
联系人 | other |
message.toContact() |
✅ | ❌ | ❌ |
视频展示
答辩报告
未来与展望
- 对 walnut 进行细节的补充和完善。
- 尽可能增加对其他功能的支持、并且持序维护。
Author: @fabian