From 6e06e1774c9fa3bc61786a0b07224fc2be2783bf Mon Sep 17 00:00:00 2001
From: NickWang <brotherstyx@gmail.com>
Date: Thu, 16 Jun 2022 12:35:58 +0800
Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20channel?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/mixins/message-mixin.ts |  5 +++++
 src/mixins/sayable-mixin.ts |  4 ++++
 src/mods/payloads.ts        |  2 ++
 src/schemas/channel.ts      | 10 ++++++++++
 src/schemas/message.ts      |  1 +
 src/schemas/mod.ts          |  5 +++++
 src/schemas/sayable.ts      |  4 ++++
 7 files changed, 31 insertions(+)
 create mode 100644 src/schemas/channel.ts

diff --git a/src/mixins/message-mixin.ts b/src/mixins/message-mixin.ts
index 6ffbafd0..96a06287 100644
--- a/src/mixins/message-mixin.ts
+++ b/src/mixins/message-mixin.ts
@@ -37,6 +37,7 @@ import {
   type SayablePayload,
   sayableTypes,
 }                                 from '../schemas/sayable.js'
+import type { ChannelPayload } from '../schemas/channel.js'
 
 const filebox = (filebox: string | FileBoxInterface) => typeof filebox === 'string' ? FileBox.fromJSON(filebox) : filebox
 
@@ -67,6 +68,7 @@ const messageMixin = <MinxinBase extends typeof PuppetSkeleton & CacheMixin>(bas
     abstract messageMiniProgram  (messageId: string)                       : Promise<MiniProgramPayload>
     abstract messageUrl          (messageId: string)                       : Promise<UrlLinkPayload>
     abstract messageLocation     (messageId: string)                       : Promise<LocationPayload>
+    abstract messageChannel      (messageId: string)                       : Promise<ChannelPayload>
 
     abstract messageForward         (conversationId: string, messageId: string,)                     : Promise<void | string>
     abstract messageSendContact     (conversationId: string, contactId: string)                      : Promise<void | string>
@@ -76,6 +78,7 @@ const messageMixin = <MinxinBase extends typeof PuppetSkeleton & CacheMixin>(bas
     abstract messageSendPost        (conversationId: string, postPayload: PostPayload)               : Promise<void | string>
     abstract messageSendText        (conversationId: string, text: string, mentionIdList?: string[]) : Promise<void | string>
     abstract messageSendUrl         (conversationId: string, urlLinkPayload: UrlLinkPayload)         : Promise<void | string>
+    abstract messageSendChannel     (conversationId: string, channelPayload: ChannelPayload)         : Promise<void | string>
 
     abstract messageRecall (messageId: string) : Promise<boolean>
 
@@ -280,6 +283,8 @@ const messageMixin = <MinxinBase extends typeof PuppetSkeleton & CacheMixin>(bas
           return this.messageSendText(conversationId, sayable.payload.text, sayable.payload.mentions)
         case sayableTypes.Post:
           return this.messageSendPost(conversationId, sayable.payload)
+        case sayableTypes.Channel:
+          return this.messageSendChannel(conversationId, sayable.payload)
         default:
           throw new Error('unsupported sayable payload: ' + JSON.stringify(sayable))
       }
diff --git a/src/mixins/sayable-mixin.ts b/src/mixins/sayable-mixin.ts
index 97f5faf3..dc985227 100644
--- a/src/mixins/sayable-mixin.ts
+++ b/src/mixins/sayable-mixin.ts
@@ -60,6 +60,10 @@ const sayableMixin = <MixinBase extends typeof PuppetSkeleton & MessageMixin & P
           const postPayload = await this.postPayload(sayableId)
           return sayablePayloads.post(postPayload)
         }
+        case MessageType.Channel: {
+          const channelPayload = await this.messageChannel(sayableId)
+          return sayablePayloads.channel(channelPayload)
+        }
 
         default:
           log.warn('PuppetSayableMixin',
diff --git a/src/mods/payloads.ts b/src/mods/payloads.ts
index c76502a8..7a223e92 100644
--- a/src/mods/payloads.ts
+++ b/src/mods/payloads.ts
@@ -35,6 +35,7 @@ import type {
   TapPayload,
   UrlLinkPayload,
   SayablePayload,
+  ChannelPayload,
 }                           from '../schemas/mod.js'
 import {
   sayablePayloads,
@@ -79,6 +80,7 @@ export type {
   SayablePayload            as Sayable,
   TapPayload                as Tap,
   UrlLinkPayload            as UrlLink,
+  ChannelPayload            as Channel,
 }
 export {
   sayablePayloads as sayable, // Sayable payload creators
diff --git a/src/schemas/channel.ts b/src/schemas/channel.ts
new file mode 100644
index 00000000..a914353f
--- /dev/null
+++ b/src/schemas/channel.ts
@@ -0,0 +1,10 @@
+export interface ChannelPayload {
+  avatar: string,
+  coverUrl: string,
+  desc: string,
+  extras: string,
+  feedType: number,
+  nickname: string,
+  thumbUrl: string,
+  url: string,
+}
diff --git a/src/schemas/message.ts b/src/schemas/message.ts
index 6492b44c..f911b9c0 100644
--- a/src/schemas/message.ts
+++ b/src/schemas/message.ts
@@ -20,6 +20,7 @@ export enum MessageType {
   Url         = 14,   // Url(5)
   Video       = 15,   // Video(4), Video(43)
   Post        = 16,   // Moment, Channel, Tweet, etc
+  Channel     = 17,   // Channel
 }
 
 /**
diff --git a/src/schemas/mod.ts b/src/schemas/mod.ts
index 0e915008..bb87be2b 100644
--- a/src/schemas/mod.ts
+++ b/src/schemas/mod.ts
@@ -92,6 +92,10 @@ import type {
   ChatEventName,
 }                         from './puppet.js'
 
+import type {
+  ChannelPayload,
+} from './channel.js'
+
 import {
   sayablePayloads,
   sayableTypes,
@@ -168,5 +172,6 @@ export {
   type TapPayload,
   type TapQueryFilter,
   type UrlLinkPayload,
+  type ChannelPayload,
   YOU,
 }
diff --git a/src/schemas/sayable.ts b/src/schemas/sayable.ts
index b3ea4929..5ad3e220 100644
--- a/src/schemas/sayable.ts
+++ b/src/schemas/sayable.ts
@@ -6,6 +6,7 @@ import { MessageType }              from './message.js'
 import type { LocationPayload }     from './location.js'
 import type { UrlLinkPayload }      from './url-link.js'
 import type { MiniProgramPayload }  from './mini-program.js'
+import type { ChannelPayload }      from './channel.js'
 import type {
   PostPayload,
   SayablePayloadPost,
@@ -21,6 +22,7 @@ const payloadLocation    = (locationPayload: LocationPayload)       => ({ ...loc
 const payloadMiniProgram = (miniProgramPayload: MiniProgramPayload) => ({ ...miniProgramPayload })
 const payloadUrlLink     = (urlLinkPayload: UrlLinkPayload)         => ({ ...urlLinkPayload })
 const payloadPost        = (postPayload: PostPayload)               => ({ ...postPayload })
+const payloadChannel     = (channelPayload: ChannelPayload)         => ({ ...channelPayload })
 
 /**
  * using `types` as a static typed string name list for `createAction`
@@ -61,6 +63,7 @@ const location    = createAction(sayableTypes.Location,    payloadLocation)()
 const miniProgram = createAction(sayableTypes.MiniProgram, payloadMiniProgram)()
 const url         = createAction(sayableTypes.Url,         payloadUrlLink)()
 const post        = createAction(sayableTypes.Post,        payloadPost)()
+const channel     = createAction(sayableTypes.Channel,     payloadChannel)()
 
 /**
  * Huan(202201): Recursive type references
@@ -77,6 +80,7 @@ const sayablePayloadsNoPost = {
   text,
   url,
   video,
+  channel,
 } as const
 
 /**

From 43636873fbe6fbdc55caff230dc98e55c4765e1c Mon Sep 17 00:00:00 2001
From: NickWang <brotherstyx@gmail.com>
Date: Tue, 25 Apr 2023 11:19:12 +0800
Subject: [PATCH 2/5] 1.21.2

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 70be978b..2ab3e5c7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "wechaty-puppet",
-  "version": "1.21.1",
+  "version": "1.21.2",
   "description": "Abstract Puppet for Wechaty",
   "type": "module",
   "exports": {

From 7cdf1f0fa09c7cbec88ee5461027cf3d6611312e Mon Sep 17 00:00:00 2001
From: NickWang <brotherstyx@gmail.com>
Date: Tue, 25 Apr 2023 11:28:12 +0800
Subject: [PATCH 3/5] =?UTF-8?q?fix:=20=F0=9F=90=9B=20swc=20version=20confl?=
 =?UTF-8?q?ict?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 2ab3e5c7..ea297546 100644
--- a/package.json
+++ b/package.json
@@ -90,7 +90,7 @@
     "@chatie/git-scripts": "^0.6.2",
     "@chatie/semver": "^0.4.7",
     "@chatie/tsconfig": "^4.6.2",
-    "@swc/core": "^1.2.113",
+    "@swc/core": "1.3.44",
     "@swc/helpers": "^0.2.14",
     "@types/uuid": "^8.3.3",
     "nop": "^1.0.0",

From d5f887eacdf850a20bb7f57fc4498f24085c4336 Mon Sep 17 00:00:00 2001
From: NickWang <brotherstyx@gmail.com>
Date: Tue, 25 Apr 2023 11:28:23 +0800
Subject: [PATCH 4/5] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20channel=20type=20and?=
 =?UTF-8?q?=20channel=20live=20data?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/mods/types.ts      | 2 ++
 src/schemas/channel.ts | 9 +++++++++
 src/schemas/mod.ts     | 6 ++++--
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/mods/types.ts b/src/mods/types.ts
index 89823aad..9b955d50 100644
--- a/src/mods/types.ts
+++ b/src/mods/types.ts
@@ -12,6 +12,7 @@ import {
   PostType,
   TapType,
   sayableTypes,
+  ChannelType,
 
   CHAT_EVENT_DICT,
   PUPPET_EVENT_DICT,
@@ -32,6 +33,7 @@ export {
   PostType            as Post,
   TapType             as Tap,
   sayableTypes        as Sayable,
+  ChannelType         as Channel,
   /**
    * Huan(202201): `DirtyType as Payload` will be removed after Dec 31, 2023
    * @deprecated: use Dirty instead of Payload
diff --git a/src/schemas/channel.ts b/src/schemas/channel.ts
index a914353f..3f2264be 100644
--- a/src/schemas/channel.ts
+++ b/src/schemas/channel.ts
@@ -7,4 +7,13 @@ export interface ChannelPayload {
   nickname: string,
   thumbUrl: string,
   url: string,
+  objectId?: string,
+  objectNonceId?: string,
+}
+
+export enum ChannelType {
+  Unknown = 0,
+  Photo = 2,
+  Video = 4,
+  Live = 9,
 }
diff --git a/src/schemas/mod.ts b/src/schemas/mod.ts
index bb87be2b..1abe8900 100644
--- a/src/schemas/mod.ts
+++ b/src/schemas/mod.ts
@@ -92,8 +92,9 @@ import type {
   ChatEventName,
 }                         from './puppet.js'
 
-import type {
-  ChannelPayload,
+import {
+  type ChannelPayload,
+  ChannelType,
 } from './channel.js'
 
 import {
@@ -125,6 +126,7 @@ export {
   sayableTypes,
   ScanStatus,
   TapType,
+  ChannelType,
   type ChatEventName,
   type ContactPayload,
   type ContactQueryFilter,

From 53f8fd433abcfc361f86e380778c27466358087f Mon Sep 17 00:00:00 2001
From: NickWang <brotherstyx@gmail.com>
Date: Tue, 25 Apr 2023 11:45:09 +0800
Subject: [PATCH 5/5] =?UTF-8?q?fix:=20=F0=9F=90=9B=20lint?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/agents/cache-agent.ts          |  2 +-
 src/mixins/contact-mixin.ts        |  2 +-
 src/mixins/message-mixin.ts        |  4 ++--
 src/mixins/post-mixin.ts           |  2 +-
 src/mixins/room-member-mixin.ts    |  2 +-
 src/mixins/room-mixin.ts           |  2 +-
 src/puppet/puppet-abstract.spec.ts | 16 ++++++++--------
 src/puppet/puppet-skeleton.spec.ts |  2 +-
 8 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/src/agents/cache-agent.ts b/src/agents/cache-agent.ts
index 1a755c15..9050c23e 100644
--- a/src/agents/cache-agent.ts
+++ b/src/agents/cache-agent.ts
@@ -60,7 +60,7 @@ class CacheAgent {
      */
     const lruOptions = (maxSize = 100): QuickLruOptions<any, any> => ({
       maxAge: 15 * 60 * 1000 * 1000, // 15 minutes
-      maxSize: maxSize,
+      maxSize,
     })
 
     this.contact = new QuickLru<string, ContactPayload>(lruOptions(
diff --git a/src/mixins/contact-mixin.ts b/src/mixins/contact-mixin.ts
index 571efc98..53c933cb 100644
--- a/src/mixins/contact-mixin.ts
+++ b/src/mixins/contact-mixin.ts
@@ -100,7 +100,7 @@ const contactMixin = <MixinBase extends CacheMixin & typeof PuppetSkeleton>(mixi
         try {
           // make sure the contact id has valid payload
           await this.contactPayload(query.id)
-          return [query.id]
+          return [ query.id ]
         } catch (e) {
           log.verbose('PuppetContactMixin', 'contactSearch() payload not found for id "%s"', query.id)
           await this.contactPayloadDirty(query.id)
diff --git a/src/mixins/message-mixin.ts b/src/mixins/message-mixin.ts
index 96a06287..4204c267 100644
--- a/src/mixins/message-mixin.ts
+++ b/src/mixins/message-mixin.ts
@@ -147,7 +147,7 @@ const messageMixin = <MinxinBase extends typeof PuppetSkeleton & CacheMixin>(bas
 
     messageList (): string[] {
       log.verbose('PuppetMessageMixin', 'messageList()')
-      return [...this.cache.message.keys()]
+      return [ ...this.cache.message.keys() ]
     }
 
     async messageSearch (
@@ -162,7 +162,7 @@ const messageMixin = <MinxinBase extends typeof PuppetSkeleton & CacheMixin>(bas
         try {
           // make sure the room id has valid payload
           await this.messagePayload(query.id)
-          return [query.id]
+          return [ query.id ]
         } catch (e) {
           log.verbose('PuppetMessageMixin', 'messageSearch() payload not found for id "%s"', query.id)
           return []
diff --git a/src/mixins/post-mixin.ts b/src/mixins/post-mixin.ts
index 708e13e3..e2e414e7 100644
--- a/src/mixins/post-mixin.ts
+++ b/src/mixins/post-mixin.ts
@@ -95,7 +95,7 @@ const postMixin = <MinxinBase extends typeof PuppetSkeleton & CacheMixin>(baseMi
      */
     postList (): string[] {
       log.verbose('PuppetPostMixin', 'postList()')
-      return [...this.cache.post.keys()]
+      return [ ...this.cache.post.keys() ]
     }
 
     async postPayloadDirty (
diff --git a/src/mixins/room-member-mixin.ts b/src/mixins/room-member-mixin.ts
index 43553139..be0c3c63 100644
--- a/src/mixins/room-member-mixin.ts
+++ b/src/mixins/room-member-mixin.ts
@@ -52,7 +52,7 @@ const roomMemberMixin = <MixinBase extends typeof PuppetSkeleton & ContactMixin>
         */
       if (typeof query === 'symbol') {
         if (query === YOU) {
-          return [this.currentUserId]
+          return [ this.currentUserId ]
         }
         /**
          * Huan(202111): We use `symbol` instead of `uniq symbol` in the method argument
diff --git a/src/mixins/room-mixin.ts b/src/mixins/room-mixin.ts
index 0ff60836..80b74c1a 100644
--- a/src/mixins/room-mixin.ts
+++ b/src/mixins/room-mixin.ts
@@ -74,7 +74,7 @@ const roomMixin = <MixinBase extends typeof PuppetSkeleton & ContactMixin & Room
         try {
           // make sure the room id has valid payload
           await this.roomPayload(query.id)
-          return [query.id]
+          return [ query.id ]
         } catch (e) {
           log.verbose('PuppetRoomMixin', 'roomSearch() payload not found for id "%s"', query.id)
           await this.roomPayloadDirty(query.id)
diff --git a/src/puppet/puppet-abstract.spec.ts b/src/puppet/puppet-abstract.spec.ts
index 61d561e9..7d7a72b9 100755
--- a/src/puppet/puppet-abstract.spec.ts
+++ b/src/puppet/puppet-abstract.spec.ts
@@ -83,7 +83,7 @@ test('contactQueryFilterFunction()', async t => {
 
   void t.test('filter name by regex', async t => {
     const QUERY   = { name: REGEX_VALUE }
-    const ID_LIST = ['id1', 'id3']
+    const ID_LIST = [ 'id1', 'id3' ]
 
     const func = puppet.contactQueryFilterFactory(QUERY)
     const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id)
@@ -92,7 +92,7 @@ test('contactQueryFilterFunction()', async t => {
 
   void t.test('filter name by text', async t => {
     const QUERY = { name: TEXT_VALUE }
-    const ID_LIST = ['id2', 'id4']
+    const ID_LIST = [ 'id2', 'id4' ]
 
     const func = puppet.contactQueryFilterFactory(QUERY)
     const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id)
@@ -101,7 +101,7 @@ test('contactQueryFilterFunction()', async t => {
 
   void t.test('filter alias by regex', async t => {
     const QUERY = { alias: REGEX_VALUE }
-    const ID_LIST = ['id2', 'id4']
+    const ID_LIST = [ 'id2', 'id4' ]
 
     const func = puppet.contactQueryFilterFactory(QUERY)
     const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id)
@@ -110,7 +110,7 @@ test('contactQueryFilterFunction()', async t => {
 
   void t.test('filter alias by text', async t => {
     const QUERY = { alias: TEXT_VALUE }
-    const ID_LIST = ['id1', 'id3']
+    const ID_LIST = [ 'id1', 'id3' ]
 
     const func = puppet.contactQueryFilterFactory(QUERY)
     const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id)
@@ -119,7 +119,7 @@ test('contactQueryFilterFunction()', async t => {
 
   void t.test('filter contact existing id', async t => {
     const QUERY = { id: 'id1' }
-    const ID_LIST = ['id1']
+    const ID_LIST = [ 'id1' ]
 
     const func = puppet.contactQueryFilterFactory(QUERY)
     const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id)
@@ -186,7 +186,7 @@ test('roomQueryFilterFunction()', async t => {
 
   void t.test('filter name by regex', async t => {
     const QUERY   = { topic: REGEX_VALUE }
-    const ID_LIST = ['id2', 'id4']
+    const ID_LIST = [ 'id2', 'id4' ]
 
     const func = puppet.roomQueryFilterFactory(QUERY)
     const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id)
@@ -195,7 +195,7 @@ test('roomQueryFilterFunction()', async t => {
 
   void t.test('filter name by text', async t => {
     const QUERY = { topic: TEXT_VALUE }
-    const ID_LIST = ['id1', 'id3']
+    const ID_LIST = [ 'id1', 'id3' ]
 
     const func = puppet.roomQueryFilterFactory(QUERY)
     const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id)
@@ -204,7 +204,7 @@ test('roomQueryFilterFunction()', async t => {
 
   void t.test('filter name by existing id', async t => {
     const QUERY = { id: 'id4' }
-    const ID_LIST = ['id4']
+    const ID_LIST = [ 'id4' ]
 
     const func = puppet.roomQueryFilterFactory(QUERY)
     const idList = PAYLOAD_LIST.filter(func).map(payload => payload.id)
diff --git a/src/puppet/puppet-skeleton.spec.ts b/src/puppet/puppet-skeleton.spec.ts
index 32ad7ce0..0cde7976 100755
--- a/src/puppet/puppet-skeleton.spec.ts
+++ b/src/puppet/puppet-skeleton.spec.ts
@@ -36,7 +36,7 @@ test('emit(error, ...) with GError', async t => {
     '',
     'foo',
     [],
-    [1],
+    [ 1 ],
     {},
     { foo: 'bar' },
     new Error(),