1 |
|
2 | import type {
|
3 | CallbackQuery,
|
4 | CommonMessageBundle,
|
5 | Message,
|
6 | Update,
|
7 | } from '@telegraf/types'
|
8 | import type { Deunionize, UnionKeys } from './deunionize'
|
9 |
|
10 | type DistinctKeys<T extends object> = Exclude<UnionKeys<T>, keyof T>
|
11 |
|
12 | type Keyed<T extends object, K extends DistinctKeys<T>> = Record<K, {}> &
|
13 | Deunionize<Record<K, {}>, T>
|
14 |
|
15 | export type Filter<U extends Update> = (update: Update) => update is U
|
16 |
|
17 | export const message =
|
18 | <Ks extends DistinctKeys<Message>[]>(...keys: Ks) =>
|
19 | (
|
20 | update: Update
|
21 | ): update is Update.MessageUpdate<Keyed<Message, Ks[number]>> => {
|
22 | if (!('message' in update)) return false
|
23 | for (const key of keys) {
|
24 | if (!(key in update.message)) return false
|
25 | }
|
26 | return true
|
27 | }
|
28 |
|
29 | export const editedMessage =
|
30 | <Ks extends DistinctKeys<CommonMessageBundle>[]>(...keys: Ks) =>
|
31 | (
|
32 | update: Update
|
33 | ): update is Update.EditedMessageUpdate<
|
34 | Keyed<CommonMessageBundle, Ks[number]>
|
35 | > => {
|
36 | if (!('edited_message' in update)) return false
|
37 | for (const key of keys) {
|
38 | if (!(key in update.edited_message)) return false
|
39 | }
|
40 | return true
|
41 | }
|
42 |
|
43 | export const channelPost =
|
44 | <Ks extends DistinctKeys<Message>[]>(...keys: Ks) =>
|
45 | (
|
46 | update: Update
|
47 | ): update is Update.ChannelPostUpdate<Keyed<Message, Ks[number]>> => {
|
48 | if (!('channel_post' in update)) return false
|
49 | for (const key of keys) {
|
50 | if (!(key in update.channel_post)) return false
|
51 | }
|
52 | return true
|
53 | }
|
54 |
|
55 | export const editedChannelPost =
|
56 | <Ks extends DistinctKeys<CommonMessageBundle>[]>(...keys: Ks) =>
|
57 | (
|
58 | update: Update
|
59 | ): update is Update.EditedChannelPostUpdate<
|
60 | Keyed<CommonMessageBundle, Ks[number]>
|
61 | > => {
|
62 | if (!('edited_channel_post' in update)) return false
|
63 | for (const key of keys) {
|
64 | if (!(key in update.edited_channel_post)) return false
|
65 | }
|
66 | return true
|
67 | }
|
68 |
|
69 | export const callbackQuery =
|
70 | <Ks extends DistinctKeys<CallbackQuery>[]>(...keys: Ks) =>
|
71 | (
|
72 | update: Update
|
73 | ): update is Update.CallbackQueryUpdate<Keyed<CallbackQuery, Ks[number]>> => {
|
74 | if (!('callback_query' in update)) return false
|
75 | for (const key of keys) {
|
76 | if (!(key in update.callback_query)) return false
|
77 | }
|
78 | return true
|
79 | }
|
80 |
|
81 | export const either =
|
82 | <Us extends Update[]>(
|
83 | ...filters: {
|
84 | [UIdx in keyof Us]: Filter<Us[UIdx]>
|
85 | }
|
86 | ) =>
|
87 | (update: Update): update is Us[number] => {
|
88 | for (const filter of filters) {
|
89 | if (filter(update)) return true
|
90 | }
|
91 | return false
|
92 | }
|