Skip to main content
Deno 2 is finally here 🎉️
Learn more
Module

x/grammy_menu/mod.ts>MenuRange

Interactive menus for grammY.
Go to Latest
class MenuRange
import { MenuRange } from "https://deno.land/x/grammy_menu@v1.2.2/mod.ts";

A menu range is a two-dimensional array of menu buttons.

This array is a part of the total two-dimensional array of menu buttons. This is mostly useful if you want to dynamically generate the structure of the menu on the fly.

Properties

[ops]: MaybeDynamicRange<C>[]

Internal list of range generator functions

Methods

add(...btns: MenuButton<C>[])

This method is used internally whenever new buttons are added. Adds the buttons to the current row.

addRange(...range: MaybeDynamicRange<C>[])

This method is used internally whenever a new range is added.

append(range: MaybeRawRange<C>)

Appends a given range to this range. This will effectively replay all operations of the given range onto this range.

back(text: MaybeDynamicString<C>, ...middleware: MenuMiddleware<C>[]): this

Adds a text button that performs a navigation to the parent menu via ctx.menu.back().

back(text: TextAndPayload<C>, ...middleware: MenuMiddleware<C & { match: string; }>[]): this
back(text: MaybePayloadString<C>, ...middleware: MenuMiddleware<C>[]): this
dynamic(rangeBuilder: (ctx: C, range: MenuRange<C>) => MaybePromise<MaybeRawRange<C> | void>)

This is a dynamic way to initialize menu. A typical use case is when you want to create an arbitrary menu, using the data from ctx.session:

const menu = new Menu('root')
menu.dynamic(ctx => ctx.session.data.reduce((range, entry) => range.text(entry)), new Menu.Builder())
bot.command("start", async (ctx) => {
  await ctx.reply("Menu", {
     reply_markup: menu,
  });
});
game(text: MaybeDynamicString<C>)

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.

login(text: MaybeDynamicString<C>, loginUrl: string | LoginUrl)

Adds a new login button. This can be used as a replacement for the Telegram Login Widget. You must specify an HTTPS URL used to automatically authorize the user.

pay(text: MaybeDynamicString<C>)

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 and can only be used in invoice messages.

row()

Adds a 'line break'. Call this method to make sure that the next added buttons will be on a new row.

submenu(
text: MaybeDynamicString<C>,
menu: string,
...middleware: MenuMiddleware<C>[],
): this

Adds a button that navigates to a given submenu when pressed. You can pass in the identifier of another menu instance. This way, you can effectively create a network of menus with navigation between them.

It is necessary that you register the targeted submenu by calling menu.register(submenu). Otherwise, no navigation can be performed. Note that you then don't need to call bot.use(submenu) anymore, all registered submenus will automatically become interactive, too.

You can also navigate to this submenu manually by calling ctx.menu.nav('sub-id'), where 'sub-id' is the identifier of the submenu.

You can call submenu.back() to add a button that navigates back to the parent menu, i.e. the menu at which you registered the submenu.

You can get back the submenu instance by calling parent.at('sub-id'), where 'sub-id' is the identifier you passed to the submenu.

submenu(
text: TextAndPayload<C>,
menu: string,
...middleware: MenuMiddleware<C & { match: string; }>[],
): this
submenu(
text: MaybePayloadString<C>,
menu: string,
...middleware: MenuMiddleware<C>[],
): this
switchInline(text: MaybeDynamicString<C>, query?)

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:

// Listen for specifc query
bot.inlineQuery('my-query', ctx => { ... })
// Listen for any query
bot.on('inline_query', ctx => { ... })
switchInlineChosen(text: MaybeDynamicString<C>, query?: SwitchInlineQueryChosenChat)

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:

bot.on('inline_query', ctx => { ... })
switchInlineCurrent(text: MaybeDynamicString<C>, query?)

Adds a new inline query button that acts 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:

// Listen for specifc query
bot.inlineQuery('my-query', ctx => { ... })
// Listen for any query
bot.on('inline_query', ctx => { ... })
text(text: MaybeDynamicString<C>, ...middleware: MenuMiddleware<C>[]): this

Adds a new text button. You may pass any number of listeners. They will be called when the button is pressed.

menu.text('Hit me!', ctx => ctx.reply('Ouch!'))

If you pass several listeners, make sure that you understand what middleware is.

You can also use this method to register a button that depends on the current context.

function greetInstruction(ctx: Context): string {
  const username = ctx.from?.first_name
  return `Greet ${username ?? 'me'}!`,
}

const menu = new Menu('my-menu')
  .text(greetInstruction, ctx => ctx.reply("I'm too shy."))
bot.use(menu)

// This will send a menu with one text button, and the text has the name
// of the user that the bot is replying to.
bot.on('message', ctx => ctx.reply('What shall I do?', { reply_markup: menu }))

If you base the text on session data, you can easily create a settings panel with toggle buttons.

// Button will toggle between 'Yes' and 'No' when pressed
menu.text(ctx => ctx.session.flag ? 'Yes' : 'No', async ctx => {
  ctx.session.flag = !ctx.session.flag
  await ctx.menu.update()
})
text(text: TextAndPayload<C>, ...middleware: MenuMiddleware<C & { match: string; }>[]): this
text(text: MaybePayloadString<C>, ...middleware: MenuMiddleware<C>[]): this
url(text: MaybeDynamicString<C>, url: MaybeDynamicString<C>)

Adds a new URL button. Telegram clients will open the provided URL when the button is pressed. Note that they will not notify your bot when that happens, so you cannot react to this button.

webApp(text: MaybeDynamicString<C>, url: string)

Adds a new web app button, confer https://core.telegram.org/bots/webapps