-
Notifications
You must be signed in to change notification settings - Fork 99
/
keyboard.ts
266 lines (262 loc) · 8.81 KB
/
keyboard.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
import { KeyboardButton, InlineKeyboardButton, LoginUrl } from '../platform.ts'
/**
* Use this class to simplify building a keyboard (something like this:
* https://core.telegram.org/bots#keyboards).
*
* ```ts
* // Build a keyboard:
* const keyboard = new Keyboard()
* .text('A').text('B').row()
* .text('C').text('D')
*
* // Now you can either pass it directly:
* ctx.reply('text', {
* reply_markup: keyboard
* })
* // Or if you need to specify more options in `reply_markup`:
* ctx.reply('text', {
* reply_markup: {
* parse_mode: 'HTML',
* keyboard: keyboard.build(), // note the `build` call
* }
* })
* ```
*/
export class Keyboard {
/**
* The nested array that holds the keyboard. It will be extended every time
* you call one of the provided methods.
*/
public readonly keyboard: KeyboardButton[][] = [[]]
/**
* Allows you to add your own `KeyboardButton` objects if you already have
* them for some reason. You most likely want to call one of the other
* methods.
*
* @param buttons the buttons to add
*/
add(...buttons: KeyboardButton[]) {
this.keyboard[this.keyboard.length - 1]?.push(...buttons)
return this
}
/**
* Adds a 'line break'. Call this method to make sure that the next added
* buttons will be on a new row.
*
* You may pass a number of `KeyboardButton` objects if you already have the
* instances for some reason. You most likely don't want to pass any
* arguments to `row`.
*
* @param buttons a number of buttons to add to the next row
*/
row(...buttons: KeyboardButton[]) {
this.keyboard.push(buttons)
return this
}
/**
* Adds a new text button. This button will simply send the given text as a
* text message back to your bot if a user clicks on it.
*
* @param text the text to display
*/
text(text: string) {
return this.add({ text })
}
/**
* Adds a new contact request button. The user's phone number will be sent
* as a contact when the button is pressed. Available in private chats only.
*
* @param text the text to display
*/
requestContact(text: string) {
return this.add({ text, request_contact: true })
}
/**
* Adds a new location request button. The user's current location will be
* sent when the button is pressed. Available in private chats only.
*
* @param text the text to display
*/
requestLocation(text: string) {
return this.add({ text, request_location: true })
}
/**
* Adds a new poll request button. The user will be asked to create a poll
* and send it to the bot when the button is pressed. Available in private
* chats only.
*
* @param text the text to display
* @param type the type of permitted polls to create, omit if the user may send a poll of any type
*/
requestPoll(text: string, type?: 'quiz' | 'regular') {
return this.add({ text, request_poll: { type } })
}
/**
* Return the resulting keyboard that was built. May be called in the end if
* necessary so you can specify more options in `reply_markup`.
*/
build() {
return this.keyboard
}
}
/**
* Use this class to simplify building an inline keyboard (something like this:
* https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating).
*
* ```ts
* // Build an inline keyboard:
* const keyboard = new InlineKeyboard()
* .text('A').text('B', 'callack-data').row()
* .text('C').text('D').row()
* .url('Telegram', 'telegram.org')
*
* // Now you can either pass it directly:
* ctx.reply('text', {
* reply_markup: keyboard
* })
* // Or if you need to specify more options in `reply_markup`:
* ctx.reply('text', {
* reply_markup: {
* parse_mode: 'HTML',
* inline_keyboard: keyboard.build(), // note the `build` call
* }
* })
* ```
*/
export class InlineKeyboard {
/**
* The nested array that holds the inline keyboard. It will be extended
* every time you call one of the provided methods.
*/
public readonly inline_keyboard: InlineKeyboardButton[][] = [[]]
/**
* Allows you to add your own `InlineKeyboardButton` objects if you already
* have them for some reason. You most likely want to call one of the other
* methods.
*
* @param buttons the buttons to add
*/
add(...buttons: InlineKeyboardButton[]) {
this.inline_keyboard[this.inline_keyboard.length - 1]?.push(...buttons)
return this
}
/**
* Adds a 'line break'. Call this method to make sure that the next added
* buttons will be on a new row.
*
* You may pass a number of `InlineKeyboardButton` objects if you already
* have the instances for some reason. You most likely don't want to pass
* any arguments to `row`.
*
* @param buttons a number of buttons to add to the next row
*/
row(...buttons: InlineKeyboardButton[]) {
this.inline_keyboard.push(buttons)
return this
}
/**
* Adds a new URL button. Telegram clients will open the provided URL when
* the button is pressed.
*
* @param text the text to display
* @param url HTTP or tg:// url to be opened when button is pressed
*/
url(text: string, url: string) {
return this.add({ text, url })
}
/**
* Adds a new login button. This can be used as a replacement for the
* Telegram Login Widget. You must specify an HTTP URL used to automatically
* authorize the user.
*
* @param text the text to display
* @param loginUrl the login URL as string or `LoginUrl` object
*/
login(text: string, loginUrl: string | LoginUrl) {
return this.add({
text,
login_url:
typeof loginUrl === 'string' ? { url: loginUrl } : loginUrl,
})
}
/**
* Adds a new callback query button. The button contains a text and a custom
* payload. This payload will be sent back to your bot when the button is
* pressed. If you omit the payload, the display text will be sent back to
* your bot.
*
* Your bot will receive an update every time a user presses any of the text
* buttons. You can listen to these updates like this:
* ```ts
* bot.on('callback_query:data', ctx => { ... })
* ```
*
* @param text the text to display
* @param data the callback data to send back to your bot (default = text)
*/
text(text: string, data = text) {
return this.add({ text, callback_data: data })
}
/**
* Adds a new inline query button. Telegram clients will let the user pick a
* chat when this button is pressed. This will start an inline query. The
* selected chat will be prefilled with the name of your bot. You may
* provide a text that is specified along with it.
*
* Your bot will in turn receive updates for inline queries. You can listen
* to inline query updates like this:
* ```ts
* bot.on('inline_query', ctx => { ... })
* ```
*
* @param text the text to display
* @param query the (optional) inline query string to prefill
*/
switchInline(text: string, query = '') {
return this.add({ text, switch_inline_query: query })
}
/**
* Adds a new inline query button that act on the current chat. The selected
* chat will be prefilled with the name of your bot. You may provide a text
* that is specified along with it. This will start an inline query.
*
* Your bot will in turn receive updates for inline queries. You can listen
* to inline query updates like this:
* ```ts
* bot.on('inline_query', ctx => { ... })
* ```
*
* @param text the text to display
* @param query the (optional) inline query string to prefill
*/
switchInlineCurrent(text: string, query = '') {
return this.add({ text, switch_inline_query_current_chat: query })
}
/**
* Adds a new game query button, confer https://core.telegram.org/bots/api#games
*
* This type of button must always be the first button in the first row.
*
* @param text the text to display
*/
game(text: string) {
return this.add({ text, callback_game: {} })
}
/**
* Adds a new payment button, confer https://core.telegram.org/bots/api#payments
*
* This type of button must always be the first button in the first row.
*
* @param text the text to display
*/
pay(text: string) {
return this.add({ text, pay: true })
}
/**
* Return the resulting inline keyboard that was built. May be called in the
* end if necessary so you can specify more options in `reply_markup`.
*/
build() {
return this.inline_keyboard
}
}