Skip to content

Commit 498b89f

Browse files
committed
add sayable & post payloads, workaround for #180
1 parent 387db13 commit 498b89f

File tree

2 files changed

+210
-0
lines changed

2 files changed

+210
-0
lines changed

src/schemas/post.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import type {
2+
SayablePayloadNoPost,
3+
sayableTypes,
4+
} from './sayable.js'
5+
6+
/**
7+
* Huan(202201): Recursive type references
8+
* @link https://github.com/microsoft/TypeScript/pull/33050#issuecomment-1002455128
9+
*/
10+
interface SayablePayloadPost {
11+
type: typeof sayableTypes.Post
12+
// eslint-disable-next-line no-use-before-define
13+
payload: PostPayload
14+
}
15+
16+
/**
17+
* Issue #2245 - https://github.com/wechaty/wechaty/issues/2245
18+
*
19+
* There have three types of a Post:
20+
*
21+
* 1. Original (原创)
22+
* 2. Reply (评论, comment)
23+
* 3. RePost (转发, retweet)
24+
*
25+
* | Type | Root ID | Parent ID |
26+
* | ---------| -------- | ---------- |
27+
* | Original | n/a | n/a |
28+
* | Reply | `rootId` | `parentId` |
29+
* | Repost | n/a | `parentId` |
30+
*
31+
*/
32+
interface PostPayloadBase {
33+
parentId? : string // `undefined` means it's original
34+
rootId? : string // `undefined` means it's not a reply (original or repost)
35+
}
36+
37+
interface PostPayloadClient extends PostPayloadBase {
38+
id? : undefined
39+
/**
40+
* Recursive type references
41+
* @link https://github.com/microsoft/TypeScript/pull/33050#issuecomment-1002455128
42+
*/
43+
sayableList: (SayablePayloadNoPost | SayablePayloadPost)[]
44+
}
45+
46+
interface PostPayloadServer extends PostPayloadBase {
47+
id : string
48+
sayableList: string[] // The message id(s) for this post.
49+
50+
contactId: string
51+
timestamp: number
52+
53+
descendantNum : number
54+
tapNum : number
55+
56+
// The tap(i.e., liker) information need to be fetched from another API
57+
}
58+
59+
type PostPayload =
60+
| PostPayloadClient
61+
| PostPayloadServer
62+
63+
const isPostPayloadClient = (payload: PostPayload): payload is PostPayloadClient =>
64+
payload instanceof Object
65+
&& !payload.id
66+
&& Array.isArray(payload.sayableList)
67+
&& payload.sayableList.length > 0
68+
&& payload.sayableList[0] instanceof Object
69+
&& typeof payload.sayableList[0].type !== 'undefined'
70+
71+
const isPostPayloadServer = (payload: PostPayload): payload is PostPayloadServer =>
72+
payload instanceof Object
73+
&& !!payload.id
74+
&& Array.isArray(payload.sayableList)
75+
&& payload.sayableList.length > 0
76+
&& typeof payload.sayableList[0] === 'string'
77+
78+
/**
79+
* Huan(202201): This enum type value MUST be keep unchanged across versions
80+
* because the puppet service client/server might has different versions of the puppet
81+
*/
82+
enum PostTapType {
83+
Unspecified = 0,
84+
Like = 1,
85+
}
86+
87+
type PostTapListPayload = {
88+
[key in PostTapType]?: {
89+
contactId: string[]
90+
timestamp: number[]
91+
}
92+
}
93+
94+
export {
95+
isPostPayloadClient,
96+
isPostPayloadServer,
97+
PostTapType,
98+
type SayablePayloadPost,
99+
type PostPayload,
100+
type PostPayloadClient,
101+
type PostPayloadServer,
102+
type PostTapListPayload,
103+
}

src/schemas/sayable.ts

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/* eslint-disable sort-keys */
2+
import { createAction } from 'typesafe-actions'
3+
import type { FileBoxInterface } from 'file-box'
4+
5+
import { MessageType } from './message.js'
6+
import type { LocationPayload } from './location.js'
7+
import type { UrlLinkPayload } from './url-link'
8+
import type { MiniProgramPayload } from './mini-program.js'
9+
import type { PostPayload } from './post.js'
10+
11+
const payloadContact = (contactId: string) => ({ contactId })
12+
const payloadFilebox = (filebox: string | FileBoxInterface) => ({ filebox })
13+
const payloadText = (text: string) => ({ text })
14+
// expand/merge the payload altogether
15+
const payloadLocation = (locationPayload: LocationPayload) => ({ ...locationPayload })
16+
const payloadMiniProgram = (miniProgramPayload: MiniProgramPayload) => ({ ...miniProgramPayload })
17+
const payloadUrlLink = (urlLinkPayload: UrlLinkPayload) => ({ ...urlLinkPayload })
18+
const payloadPost = (postPayload: PostPayload) => ({ ...postPayload })
19+
20+
/**
21+
* using `types` as a static typed string name list for `createAction`
22+
*
23+
* Huan(202201): if we remove the `(() => ({}))()`, then the typing will fail.
24+
* FIXME: remove the `(() => ({}))()` after we fix the issue.
25+
*/
26+
const sayableTypes = (() => ({
27+
...Object.keys(MessageType)
28+
.filter(k => isNaN(Number(k)))
29+
.reduce((acc, cur) => ({
30+
...acc,
31+
[cur]: cur,
32+
}), {}),
33+
} as {
34+
[k in keyof typeof MessageType]: k
35+
}))()
36+
37+
/**
38+
* Simple data
39+
*/
40+
const contact = createAction(sayableTypes.Contact, payloadContact)()
41+
const text = createAction(sayableTypes.Text, payloadText)()
42+
// (conversationId: string, text: string, mentionIdList?: string[]) => ({ conversationId, mentionIdList, text }
43+
44+
/**
45+
* FileBoxs
46+
*/
47+
const attatchment = createAction(sayableTypes.Attachment, payloadFilebox)()
48+
const audio = createAction(sayableTypes.Audio, payloadFilebox)()
49+
const emoticon = createAction(sayableTypes.Emoticon, payloadFilebox)()
50+
const image = createAction(sayableTypes.Image, payloadFilebox)()
51+
const video = createAction(sayableTypes.Video, payloadFilebox)()
52+
53+
/**
54+
* Payload data
55+
*/
56+
const location = createAction(sayableTypes.Location, payloadLocation)()
57+
const miniProgram = createAction(sayableTypes.MiniProgram, payloadMiniProgram)()
58+
const url = createAction(sayableTypes.Url, payloadUrlLink)()
59+
const post = createAction(sayableTypes.Post, payloadPost)()
60+
61+
type SayablePayloadPost = ReturnType<typeof post>
62+
63+
/**
64+
* Huan(202201): Recursive type references
65+
* @link https://github.com/microsoft/TypeScript/pull/33050#issuecomment-1002455128
66+
*/
67+
const sayablePayloadsNoPost = {
68+
attatchment,
69+
audio,
70+
contact,
71+
emoticon,
72+
image,
73+
location,
74+
miniProgram,
75+
text,
76+
url,
77+
video,
78+
} as const
79+
80+
const sayablePayloads = {
81+
...sayablePayloadsNoPost,
82+
post,
83+
} as const
84+
85+
/**
86+
* Huan(202201): Recursive type references
87+
* @link https://github.com/microsoft/TypeScript/pull/33050#issuecomment-1002455128
88+
*/
89+
type SayablePayloadNoPost = ReturnType<typeof sayablePayloadsNoPost[keyof typeof sayablePayloadsNoPost]>
90+
91+
// TODO: add an unit test to confirm that all unsupported type are listed here
92+
type SayablePayloadUnsupportedType =
93+
| 'ChatHistory'
94+
| 'GroupNote'
95+
| 'Recalled'
96+
| 'RedEnvelope'
97+
| 'Transfer'
98+
| 'Unknown'
99+
100+
export {
101+
sayablePayloads,
102+
sayableTypes,
103+
type SayablePayloadNoPost,
104+
type SayablePayloadPost,
105+
106+
type SayablePayloadUnsupportedType,
107+
}

0 commit comments

Comments
 (0)