UNPKG

2.52 kBPlain TextView Raw
1/* eslint-disable @typescript-eslint/ban-types */
2import type {
3 CallbackQuery,
4 CommonMessageBundle,
5 Message,
6 Update,
7} from '@telegraf/types'
8import type { Deunionize, UnionKeys } from './deunionize'
9
10type DistinctKeys<T extends object> = Exclude<UnionKeys<T>, keyof T>
11
12type Keyed<T extends object, K extends DistinctKeys<T>> = Record<K, {}> &
13 Deunionize<Record<K, {}>, T>
14
15export type Filter<U extends Update> = (update: Update) => update is U
16
17export 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
29export 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
43export 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
55export 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
69export 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
81export 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 }