docs/tgbotapi/guides/keyboards.html
2024-04-22 10:45:00 +00:00

3052 lines
126 KiB
HTML

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Single documentation place for all Insanus Mokrassar libraries">
<meta name="author" content="Ovsiannikov Aleksei">
<link rel="canonical" href="https://docs.inmo.dev/tgbotapi/guides/keyboards.html">
<link rel="prev" href="../introduction/first-bot.html">
<link rel="next" href="../updates/updates-filters.html">
<link rel="icon" href="/resources/images/favicon.png">
<meta name="generator" content="mkdocs-1.5.3, mkdocs-material-9.5.13">
<title>Keyboards Guide - InMo Docs</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.7e359304.min.css">
<link rel="stylesheet" href="../../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="/resources/stylesheets/navigation.css">
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
<script id="__analytics">function __md_analytics(){function n(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],n("js",new Date),n("config","G-615VY8CQSM"),document.addEventListener("DOMContentLoaded",function(){document.forms.search&&document.forms.search.query.addEventListener("blur",function(){this.value&&n("event","search",{search_term:this.value})}),document$.subscribe(function(){var a=document.forms.feedback;if(void 0!==a)for(var e of a.querySelectorAll("[type=submit]"))e.addEventListener("click",function(e){e.preventDefault();var t=document.location.pathname,e=this.getAttribute("data-md-value");n("event","feedback",{page:t,data:e}),a.firstElementChild.disabled=!0;e=a.querySelector(".md-feedback__note [data-md-value='"+e+"']");e&&(e.hidden=!1)}),a.hidden=!1}),location$.subscribe(function(e){n("config","G-615VY8CQSM",{page_path:e.pathname})})});var e=document.createElement("script");e.async=!0,e.src="https://www.googletagmanager.com/gtag/js?id=G-615VY8CQSM",document.getElementById("__analytics").insertAdjacentElement("afterEnd",e)}</script>
<script>"undefined"!=typeof __md_analytics&&__md_analytics()</script>
</head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="teal" data-md-color-accent="cyan">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#keyboards-guide" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../../index.html" title="InMo Docs" class="md-header__button md-logo" aria-label="InMo Docs" data-md-component="logo">
<img src="/resources/images/logo.png" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
InMo Docs
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Keyboards Guide
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="teal" data-md-color-accent="cyan" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69Z"/></svg>
</label>
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="blue-grey" data-md-color-accent="light-blue" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12c0-2.42-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69Z"/></svg>
</label>
</form>
<script>var media,input,key,value,palette=__md_get("__palette");if(palette&&palette.color){"(prefers-color-scheme)"===palette.color.media&&(media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']"),palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent"));for([key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91 1.61 0 2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08Z"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/InsanusMokrassar/docs" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
</div>
<div class="md-source__repository">
InsanusMokrassar/docs
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="../../index.html" class="md-tabs__link">
Home
</a>
</li>
<li class="md-tabs__item">
<a href="../../micro_utils/index.html" class="md-tabs__link">
MicroUtils
</a>
</li>
<li class="md-tabs__item md-tabs__item--active">
<a href="../index.html" class="md-tabs__link">
Telegram Bot API
</a>
</li>
<li class="md-tabs__item">
<a href="../../plagubot/index.html" class="md-tabs__link">
PlaguBot (TBD)
</a>
</li>
<li class="md-tabs__item">
<a href="../../krontab/index.html" class="md-tabs__link">
Krontab
</a>
</li>
<li class="md-tabs__item">
<a href="../../kslog/index.html" class="md-tabs__link">
KSLog
</a>
</li>
<li class="md-tabs__item">
<a href="../../navigation/index.html" class="md-tabs__link">
Navigation
</a>
</li>
<li class="md-tabs__item">
<a href="../../services/index.html" class="md-tabs__link">
Services
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../../index.html" title="InMo Docs" class="md-nav__button md-logo" aria-label="InMo Docs" data-md-component="logo">
<img src="/resources/images/logo.png" alt="logo">
</a>
InMo Docs
</label>
<div class="md-nav__source">
<a href="https://github.com/InsanusMokrassar/docs" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
</div>
<div class="md-source__repository">
InsanusMokrassar/docs
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../index.html" class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
<div class="md-nav__link md-nav__container">
<a href="../../micro_utils/index.html" class="md-nav__link ">
<span class="md-ellipsis">
MicroUtils
</span>
</a>
<label class="md-nav__link " for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
MicroUtils
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../micro_utils/resources.html" class="md-nav__link">
<span class="md-ellipsis">
Resources
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../micro_utils/startup.html" class="md-nav__link">
<span class="md-ellipsis">
Startup
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<div class="md-nav__link md-nav__container">
<a href="../index.html" class="md-nav__link ">
<span class="md-ellipsis">
Telegram Bot API
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Telegram Bot API
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="https://tgbotapi.inmo.dev" class="md-nav__link">
<span class="md-ellipsis">
KDocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../faq.html" class="md-nav__link">
<span class="md-ellipsis">
FAQ
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../logs.html" class="md-nav__link">
<span class="md-ellipsis">
Logging
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_5" >
<label class="md-nav__link" for="__nav_3_5" id="__nav_3_5_label" tabindex="">
<span class="md-ellipsis">
Introduction
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_5">
<span class="md-nav__icon md-icon"></span>
Introduction
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../introduction/before-any-bot-project.html" class="md-nav__link">
<span class="md-ellipsis">
Before any bot project
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../introduction/including-in-your-project.html" class="md-nav__link">
<span class="md-ellipsis">
Including in your project
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../introduction/proxy-setup.html" class="md-nav__link">
<span class="md-ellipsis">
Proxy setup
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../introduction/first-bot.html" class="md-nav__link">
<span class="md-ellipsis">
First bot
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_6" checked>
<label class="md-nav__link" for="__nav_3_6" id="__nav_3_6_label" tabindex="">
<span class="md-ellipsis">
Guides
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_6_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3_6">
<span class="md-nav__icon md-icon"></span>
Guides
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Keyboards Guide
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="keyboards.html" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Keyboards Guide
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#introduction" class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
<nav class="md-nav" aria-label="Introduction">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#keyboard-types" class="md-nav__link">
<span class="md-ellipsis">
Keyboard Types
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#simple-keyboard-interactions" class="md-nav__link">
<span class="md-ellipsis">
Simple Keyboard Interactions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#extended-keyboard-interactions" class="md-nav__link">
<span class="md-ellipsis">
Extended Keyboard Interactions
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#basic-api-classes" class="md-nav__link">
<span class="md-ellipsis">
Basic API &amp; Classes
</span>
</a>
<nav class="md-nav" aria-label="Basic API & Classes">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#keyboards" class="md-nav__link">
<span class="md-ellipsis">
Keyboards
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#buttons" class="md-nav__link">
<span class="md-ellipsis">
Buttons
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#matrices" class="md-nav__link">
<span class="md-ellipsis">
Matrices
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#keyboards-dsl" class="md-nav__link">
<span class="md-ellipsis">
Keyboards DSL
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#working-with-keyboards" class="md-nav__link">
<span class="md-ellipsis">
Working with keyboards
</span>
</a>
<nav class="md-nav" aria-label="Working with keyboards">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#reply-keyboards" class="md-nav__link">
<span class="md-ellipsis">
Reply keyboards
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#inline-keyboards" class="md-nav__link">
<span class="md-ellipsis">
Inline keyboards
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#conclusion" class="md-nav__link">
<span class="md-ellipsis">
Conclusion
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_7" >
<label class="md-nav__link" for="__nav_3_7" id="__nav_3_7_label" tabindex="">
<span class="md-ellipsis">
Updates retrieving
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_7">
<span class="md-nav__icon md-icon"></span>
Updates retrieving
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../updates/updates-filters.html" class="md-nav__link">
<span class="md-ellipsis">
Updates filters
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../updates/long-polling.html" class="md-nav__link">
<span class="md-ellipsis">
Long polling
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../updates/webhooks.html" class="md-nav__link">
<span class="md-ellipsis">
Webhooks
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../updates/heroku.html" class="md-nav__link">
<span class="md-ellipsis">
Heroku
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_8" >
<label class="md-nav__link" for="__nav_3_8" id="__nav_3_8_label" tabindex="">
<span class="md-ellipsis">
Logic handling
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_8_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_8">
<span class="md-nav__icon md-icon"></span>
Logic handling
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../logic/api-extensions.html" class="md-nav__link">
<span class="md-ellipsis">
API Extensions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../logic/behaviour-builder-with-fsm.html" class="md-nav__link">
<span class="md-ellipsis">
Behaviour Builder with FSM
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../logic/behaviour-builder.html" class="md-nav__link">
<span class="md-ellipsis">
Behaviour Builder
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../logic/exceptions-handling.html" class="md-nav__link">
<span class="md-ellipsis">
Exceptions handling
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../logic/files-handling.html" class="md-nav__link">
<span class="md-ellipsis">
Files handling
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../logic/low-level-work-with-bots.html" class="md-nav__link">
<span class="md-ellipsis">
Low-level work with bots
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../logic/media-groups.html" class="md-nav__link">
<span class="md-ellipsis">
Media Groups
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../logic/types-conversations.html" class="md-nav__link">
<span class="md-ellipsis">
Types conversations
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../logic/updates-with-flows.html" class="md-nav__link">
<span class="md-ellipsis">
Updates with flows
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_9" >
<label class="md-nav__link" for="__nav_3_9" id="__nav_3_9_label" tabindex="">
<span class="md-ellipsis">
DSLs
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_9_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3_9">
<span class="md-nav__icon md-icon"></span>
DSLs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../dsls/keyboards.html" class="md-nav__link">
<span class="md-ellipsis">
Keyboards
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../dsls/live-location.html" class="md-nav__link">
<span class="md-ellipsis">
Live Location
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../dsls/text.html" class="md-nav__link">
<span class="md-ellipsis">
Text
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" >
<div class="md-nav__link md-nav__container">
<a href="../../plagubot/index.html" class="md-nav__link ">
<span class="md-ellipsis">
PlaguBot (TBD)
</span>
</a>
<label class="md-nav__link " for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
PlaguBot (TBD)
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../plagubot/opportunities_out_of_the_box.html" class="md-nav__link">
<span class="md-ellipsis">
Opportunities out of the box
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<div class="md-nav__link md-nav__container">
<a href="../../krontab/index.html" class="md-nav__link ">
<span class="md-ellipsis">
Krontab
</span>
</a>
<label class="md-nav__link " for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Krontab
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="https://krontab.inmo.dev/" class="md-nav__link">
<span class="md-ellipsis">
KDocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="https://insanusmokrassar.github.io/KrontabPredictor" class="md-nav__link">
<span class="md-ellipsis">
Predictor
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5_4" >
<label class="md-nav__link" for="__nav_5_4" id="__nav_5_4_label" tabindex="0">
<span class="md-ellipsis">
Introduction
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_5_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5_4">
<span class="md-nav__icon md-icon"></span>
Introduction
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../krontab/introduction/including-in-project.html" class="md-nav__link">
<span class="md-ellipsis">
Including in project
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../krontab/introduction/how-to-use.html" class="md-nav__link">
<span class="md-ellipsis">
How to use
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../krontab/introduction/faq.html" class="md-nav__link">
<span class="md-ellipsis">
FAQ
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5_5" >
<label class="md-nav__link" for="__nav_5_5" id="__nav_5_5_label" tabindex="0">
<span class="md-ellipsis">
Describing
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_5_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5_5">
<span class="md-nav__icon md-icon"></span>
Describing
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../krontab/describing/string-format.html" class="md-nav__link">
<span class="md-ellipsis">
String format
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../krontab/describing/krontabscheduler.html" class="md-nav__link">
<span class="md-ellipsis">
KrontabScheduler
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6" >
<div class="md-nav__link md-nav__container">
<a href="../../kslog/index.html" class="md-nav__link ">
<span class="md-ellipsis">
KSLog
</span>
</a>
<label class="md-nav__link " for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
KSLog
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="https://kslog.inmo.dev/" class="md-nav__link">
<span class="md-ellipsis">
KDocs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../kslog/setup.html" class="md-nav__link">
<span class="md-ellipsis">
Setup
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../kslog/logging.html" class="md-nav__link">
<span class="md-ellipsis">
Logging
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7" >
<div class="md-nav__link md-nav__container">
<a href="../../navigation/index.html" class="md-nav__link ">
<span class="md-ellipsis">
Navigation
</span>
</a>
<label class="md-nav__link " for="__nav_7" id="__nav_7_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Navigation
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../navigation/getting-started.html" class="md-nav__link">
<span class="md-ellipsis">
Getting started (TBD)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_8" >
<div class="md-nav__link md-nav__container">
<a href="../../services/index.html" class="md-nav__link ">
<span class="md-ellipsis">
Services
</span>
</a>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_8_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_8">
<span class="md-nav__icon md-icon"></span>
Services
</label>
<ul class="md-nav__list" data-md-scrollfix>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#introduction" class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
<nav class="md-nav" aria-label="Introduction">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#keyboard-types" class="md-nav__link">
<span class="md-ellipsis">
Keyboard Types
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#simple-keyboard-interactions" class="md-nav__link">
<span class="md-ellipsis">
Simple Keyboard Interactions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#extended-keyboard-interactions" class="md-nav__link">
<span class="md-ellipsis">
Extended Keyboard Interactions
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#basic-api-classes" class="md-nav__link">
<span class="md-ellipsis">
Basic API &amp; Classes
</span>
</a>
<nav class="md-nav" aria-label="Basic API & Classes">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#keyboards" class="md-nav__link">
<span class="md-ellipsis">
Keyboards
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#buttons" class="md-nav__link">
<span class="md-ellipsis">
Buttons
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#matrices" class="md-nav__link">
<span class="md-ellipsis">
Matrices
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#keyboards-dsl" class="md-nav__link">
<span class="md-ellipsis">
Keyboards DSL
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#working-with-keyboards" class="md-nav__link">
<span class="md-ellipsis">
Working with keyboards
</span>
</a>
<nav class="md-nav" aria-label="Working with keyboards">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#reply-keyboards" class="md-nav__link">
<span class="md-ellipsis">
Reply keyboards
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#inline-keyboards" class="md-nav__link">
<span class="md-ellipsis">
Inline keyboards
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#conclusion" class="md-nav__link">
<span class="md-ellipsis">
Conclusion
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/InsanusMokrassar/docs/edit/master/docs/tgbotapi/guides/keyboards.md" title="Edit this page" class="md-content__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10 20H6V4h7v5h5v3.1l2-2V8l-6-6H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h4v-2m10.2-7c.1 0 .3.1.4.2l1.3 1.3c.2.2.2.6 0 .8l-1 1-2.1-2.1 1-1c.1-.1.2-.2.4-.2m0 3.9L14.1 23H12v-2.1l6.1-6.1 2.1 2.1Z"/></svg>
</a>
<a href="https://github.com/InsanusMokrassar/docs/raw/master/docs/tgbotapi/guides/keyboards.md" title="View source of this page" class="md-content__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 18c.56 0 1 .44 1 1s-.44 1-1 1-1-.44-1-1 .44-1 1-1m0-3c-2.73 0-5.06 1.66-6 4 .94 2.34 3.27 4 6 4s5.06-1.66 6-4c-.94-2.34-3.27-4-6-4m0 6.5a2.5 2.5 0 0 1-2.5-2.5 2.5 2.5 0 0 1 2.5-2.5 2.5 2.5 0 0 1 2.5 2.5 2.5 2.5 0 0 1-2.5 2.5M9.27 20H6V4h7v5h5v4.07c.7.08 1.36.25 2 .49V8l-6-6H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h4.5a8.15 8.15 0 0 1-1.23-2Z"/></svg>
</a>
<h1 id="keyboards-guide">Keyboards Guide<a class="headerlink" href="#keyboards-guide" title="Permanent link">&para;</a></h1>
<p>This guide will help you choose the right keyboard for your needs and show you various API facilities available in the library to support your choice.</p>
<h2 id="introduction">Introduction<a class="headerlink" href="#introduction" title="Permanent link">&para;</a></h2>
<h3 id="keyboard-types">Keyboard Types<a class="headerlink" href="#keyboard-types" title="Permanent link">&para;</a></h3>
<p>The first thing you need to know is that there are two types of keyboards available in the Telegram Bot API: <a href="https://core.telegram.org/bots/features#keyboards"><strong>reply</strong></a> and <a href="https://core.telegram.org/bots/features#inline-keyboards"><strong>inline</strong></a> keyboards.</p>
<p><img alt="Keyboards comparison" src="keyboards/001.png" title="Keyboards comparison" /></p>
<div class="admonition note">
<p class="admonition-title">Resize option</p>
<p>
In the screenshots above (and in the most others) you may see usage of reply keyboards without <code>resize_keyboard</code>. In case you will use <code>resize_keyboard = true</code> the keyboard will be smaller.</p>
</div>
<p>Note the differences in the way these keyboards are shown to a user.</p>
<p>A reply keyboard is shown under the message input field.
It replaces the device&rsquo;s native input method on a mobile device.</p>
<p>An inline keyboard is shown as a part of the message in the chat.</p>
<h3 id="simple-keyboard-interactions">Simple Keyboard Interactions<a class="headerlink" href="#simple-keyboard-interactions" title="Permanent link">&para;</a></h3>
<p>When a user clicks on a simple reply keyboard button, its text is just sent in the chat.</p>
<p>When a user clicks on a simple inline keyboard button, nothing is sent to the chat.
Instead, a <a href="https://core.telegram.org/bots/api#callbackquery">callback query</a> (a fancy way to say &ldquo;a request&rdquo;) is sent directly to the bot and the button is highlighted.
It will stay highlighted until the bot acks the callback.</p>
<p><img alt="Simple keyboard interactions" src="keyboards/002.png" title="Simple keyboard interactions" /></p>
<div class="admonition note">
<p class="admonition-title">It&rsquo;s a common mistake to forget to handle callback queries</p>
<p>
It leads to the buttons being highlighted for long periods of time, which leads to a bad user experience.
Don&rsquo;t forget to handle these callbacks!</p>
</div>
<p>As new messages arrive, a reply keyboard will stay there, while the inline keyboard will stick to the message and move with it.</p>
<p><img alt="Keyboards position with multiple messages" src="keyboards/003.png" title="Keyboards position with multiple messages" /></p>
<p>Ups…
The reply keyboard is now far away from the message it was sent with.</p>
<p>Actually, they are two different unrelated entities now: the original message and the reply keyboard.
A reply keyboard persists until you explicitly <a href="https://core.telegram.org/bots/api#replykeyboardremove">remove</a> it or replace it with a different one.</p>
<div class="admonition note">
<p class="admonition-title">It&rsquo;s a common mistake to forget to remove or replace reply keyboards</p>
<p>
It leads to the keyboards being shown forever. Don&rsquo;t forget to remove reply keyboards when you don&rsquo;t need them anymore!</p>
<p>You also may use option <code>one_time_keyboard</code> and the keyboard will be automatically removed after user interaction</p>
</div>
<p>An inline keyboard could also be removed or changed by editing the original message it was attached to.</p>
<h3 id="extended-keyboard-interactions">Extended Keyboard Interactions<a class="headerlink" href="#extended-keyboard-interactions" title="Permanent link">&para;</a></h3>
<p>Keyboards are not limited to text only.
They could be used to ask users for different things, like payments, locations, phone numbers, etc.
They could be used to open arbitrary URLs or <a href="https://core.telegram.org/bots/webapps">web apps</a>.
Telegram clients process these buttons and interact with the users in the appropriate ways.</p>
<p>For the full list of options, see the official documentation on <a href="https://core.telegram.org/bots/api#keyboardbutton">reply</a> and <a href="https://core.telegram.org/bots/api#inlinekeyboardbutton">inline</a> keyboards.</p>
<p><img alt="Extended keyboard interactions" src="keyboards/004.png" title="Extended keyboard interactions" /></p>
<h2 id="basic-api-classes">Basic API &amp; Classes<a class="headerlink" href="#basic-api-classes" title="Permanent link">&para;</a></h2>
<p>Now, that you know the basics, let&rsquo;s see how to use the library.</p>
<h3 id="keyboards">Keyboards<a class="headerlink" href="#keyboards" title="Permanent link">&para;</a></h3>
<p>In Telegram Bot API keyboards are sent to the user as a part of an interaction via the <code>reply_markup</code> parameter.
More specifically, this parameter is available:</p>
<ul>
<li>in the <code>sendXXX</code> methods, like <a href="https://core.telegram.org/bots/api#sendmessage"><code>sendMessage</code></a>, <a href="https://core.telegram.org/bots/api#sendphoto"><code>sendPhoto</code></a>, <a href="sendSticker"><code>sendSticker</code></a>, etc.</li>
<li>in the <a href="https://core.telegram.org/bots/api#copymessage"><code>copyMessage</code></a> method</li>
<li>in the <code>editMessageXXX</code> methods, like <a href="https://core.telegram.org/bots/api#editmessagetext"><code>editMessageText</code></a>, <a href="https://core.telegram.org/bots/api#editmessagecaption"><code>editMessageCaption</code></a>, <a href="https://core.telegram.org/bots/api#editmessagereplymarkup"><code>editMessageReplyMarkup</code></a>, etc.
This also includes <code>stopXXX</code> methods like the <a href="https://core.telegram.org/bots/api#stopmessagelivelocation"><code>stopMessageLiveLocation</code></a> method.</li>
</ul>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p><code>editMessageReplyMarkup</code> is specifically designed to edit a message&rsquo;s inline keyboard.</p>
</div>
<p>Sending inline keyboards is also supported in inline mode through the <code>reply_markup</code> parameter of the <a href="https://core.telegram.org/bots/api#inlinequeryresult"><code>InlineQueryResult</code></a> type and its inheritors.
However, this <a href="https://core.telegram.org/bots/inline">inline mode</a> is unrelated to the inline keyboards.</p>
<p>The <code>reply_markup</code> parameter accepts four different types.
Two of them — <a href="https://core.telegram.org/bots/api#replykeyboardmarkup"><code>ReplyKeyboardMarkup</code></a> and <a href="https://core.telegram.org/bots/api#inlinekeyboardmarkup"><code>InlineKeyboardMarkup</code></a> — correspond to the reply and inline keyboards respectively.
The <a href="https://core.telegram.org/bots/api#replykeyboardremove"><code>ReplyKeyboardRemove</code></a> type is used to remove reply keyboards, but it&rsquo;s not a keyboard itself.
The last one, <a href="https://core.telegram.org/bots/api#forcereply"><code>ForceReply</code></a>, is used to force users to reply to the bot.
It is not a keyboard either, but yet another dirty hack employed by the Telegram Bot API.</p>
<p><img alt="A force reply" src="keyboards/005.png" title="A force reply" /></p>
<p>Now, in the library, the <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.abstracts.types/-with-reply-markup/index.html"><code>WithReplyMarkup</code></a> is a <a href="https://en.wikipedia.org/wiki/Marker_interface_pattern">marker interface</a> for all the interactions which could have a <code>replyMarkup</code> (represents <code>reply_markup</code>) parameter.
It is extended by the <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.requests.send.abstracts/-replying-markup-send-message-request/index.html"><code>ReplyingMarkupSendMessageRequest</code></a>, and then, finally, by classes like <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.requests.send/-send-text-message/index.html"><code>SendTextMessage</code></a>.
This, basically, corresponds to the Telegram Bot API.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>You may see all the inheritors of <code>WithReplyMarkup</code> interfaces in the corresponding <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.abstracts.types/-with-reply-markup/index.html">KDoc</a></p>
</div>
<p>The other way to send a keyboard is through the <code>replyMarkup</code> parameter of the numerous extension methods, like <a href="https://tgbotapi.inmo.dev/tgbotapi.api/dev.inmo.tgbotapi.extensions.api.send/send-message.html"><code>sendMessage</code></a>.
Those are just convenient wrappers around general interaction classes, like the aforementioned <code>SendTextMessage</code>.</p>
<h3 id="buttons">Buttons<a class="headerlink" href="#buttons" title="Permanent link">&para;</a></h3>
<p>As we already know, keyboards consist of buttons.
Button classes reside in the <code>dev.inmo.tgbotapi.types.buttons</code> package.</p>
<p>The base class for the reply keyboard buttons is the <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.types.buttons/-keyboard-button/index.html"><code>KeyboardButton</code></a>.
The base class for the inline keyboard buttons is the <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons/-inline-keyboard-button/index.html"><code>InlineKeyboardButton</code></a>.</p>
<p>See their inheritors for the full list of the available buttons.
The names are pretty self-explanatory and correspond to the Telegram Bot API.</p>
<p>For example, to send a simple reply keyboard button, use the <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.types.buttons/-simple-keyboard-button/index.html"><code>SimpleKeyboardButton</code></a> class.
To request a contact from the user through the reply, use the <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.types.buttons/-request-contact-keyboard-button/index.html"><code>RequestContactKeyboardButton</code></a> class.
To attach a URL button to the message, use the <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons/-u-r-l-inline-keyboard-button/index.html"><code>URLInlineKeyboardButton</code></a>.
And to attach a callback button, use the <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons/-callback-data-inline-keyboard-button/index.html"><code>CallbackDataInlineKeyboardButton</code></a>.</p>
<p>You get the idea.</p>
<p>So, to send a reply keyboard use the following code:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="n">bot</span><span class="p">.</span><span class="na">sendMessage</span><span class="p">(</span>
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="w"> </span><span class="n">chatId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">chat</span><span class="p">,</span>
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;What is the best Kotlin Telegram Bot API library?&quot;</span><span class="p">,</span>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a><span class="w"> </span><span class="n">replyMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ReplyKeyboardMarkup</span><span class="p">(</span>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a><span class="w"> </span><span class="n">keyboard</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">listOf</span><span class="p">(</span>
</span><span id="__span-0-6"><a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a><span class="w"> </span><span class="n">listOf</span><span class="p">(</span>
</span><span id="__span-0-7"><a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a><span class="w"> </span><span class="n">SimpleKeyboardButton</span><span class="p">(</span><span class="s">&quot;ktgbotapi&quot;</span><span class="p">),</span>
</span><span id="__span-0-8"><a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a><span class="w"> </span><span class="p">),</span>
</span><span id="__span-0-9"><a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-0-10"><a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-0-11"><a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a><span class="p">)</span>
</span></code></pre></div>
<p>And here is how you send a basic inline keyboard:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="n">bot</span><span class="p">.</span><span class="na">sendMessage</span><span class="p">(</span>
</span><span id="__span-1-2"><a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a><span class="w"> </span><span class="n">chatId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">chat</span><span class="p">,</span>
</span><span id="__span-1-3"><a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;ktgbotapi is the best Kotlin Telegram Bot API library&quot;</span><span class="p">,</span>
</span><span id="__span-1-4"><a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a><span class="w"> </span><span class="n">replyMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">InlineKeyboardMarkup</span><span class="p">(</span>
</span><span id="__span-1-5"><a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a><span class="w"> </span><span class="n">keyboard</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">listOf</span><span class="p">(</span>
</span><span id="__span-1-6"><a id="__codelineno-1-6" name="__codelineno-1-6" href="#__codelineno-1-6"></a><span class="w"> </span><span class="n">listOf</span><span class="p">(</span>
</span><span id="__span-1-7"><a id="__codelineno-1-7" name="__codelineno-1-7" href="#__codelineno-1-7"></a><span class="w"> </span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;I know&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;know&quot;</span><span class="p">),</span>
</span><span id="__span-1-8"><a id="__codelineno-1-8" name="__codelineno-1-8" href="#__codelineno-1-8"></a><span class="w"> </span><span class="n">URLInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;Learn more&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;https://github.com/InsanusMokrassar/ktgbotapi&quot;</span><span class="p">)</span>
</span><span id="__span-1-9"><a id="__codelineno-1-9" name="__codelineno-1-9" href="#__codelineno-1-9"></a><span class="w"> </span><span class="p">),</span>
</span><span id="__span-1-10"><a id="__codelineno-1-10" name="__codelineno-1-10" href="#__codelineno-1-10"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-1-11"><a id="__codelineno-1-11" name="__codelineno-1-11" href="#__codelineno-1-11"></a><span class="w"> </span><span class="p">),</span>
</span><span id="__span-1-12"><a id="__codelineno-1-12" name="__codelineno-1-12" href="#__codelineno-1-12"></a><span class="p">)</span>
</span></code></pre></div>
<p><img alt="Keyboards with ktgbotapi" src="keyboards/006.png" title="Keyboards with ktgbotapi" /></p>
<p>When we&rsquo;re done with this simple quiz, we can remove the keyboard with the following code:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="n">bot</span><span class="p">.</span><span class="na">sendMessage</span><span class="p">(</span>
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a><span class="w"> </span><span class="n">chatId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">chat</span><span class="p">,</span>
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;You&#39;re goddamn right!&quot;</span><span class="p">,</span>
</span><span id="__span-2-4"><a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a><span class="w"> </span><span class="n">replyMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ReplyKeyboardRemove</span><span class="p">()</span>
</span><span id="__span-2-5"><a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a><span class="p">)</span>
</span></code></pre></div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Don&rsquo;t forget to remove the reply keyboards!</p>
</div>
<h3 id="matrices">Matrices<a class="headerlink" href="#matrices" title="Permanent link">&para;</a></h3>
<p>Buttons in keyboards are arranged in matrices, i.e. two-dimensional arrays, or, to say in layperson&rsquo;s terms, rows and columns.
In contrast to the matrices you&rsquo;ve learned in school, keyboards are not always necessarily square.
Try it:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="n">bot</span><span class="p">.</span><span class="na">sendMessage</span><span class="p">(</span>
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a><span class="w"> </span><span class="n">chatId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">chat</span><span class="p">,</span>
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;In contrast to the matrices you&#39;ve learned in school, keyboards are not always necessary square.&quot;</span><span class="p">,</span>
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a><span class="w"> </span><span class="n">replyMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">InlineKeyboardMarkup</span><span class="p">(</span>
</span><span id="__span-3-5"><a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a><span class="w"> </span><span class="n">keyboard</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">listOf</span><span class="p">(</span>
</span><span id="__span-3-6"><a id="__codelineno-3-6" name="__codelineno-3-6" href="#__codelineno-3-6"></a><span class="w"> </span><span class="n">listOf</span><span class="p">(</span>
</span><span id="__span-3-7"><a id="__codelineno-3-7" name="__codelineno-3-7" href="#__codelineno-3-7"></a><span class="w"> </span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;1&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;1&quot;</span><span class="p">),</span>
</span><span id="__span-3-8"><a id="__codelineno-3-8" name="__codelineno-3-8" href="#__codelineno-3-8"></a><span class="w"> </span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;2&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;2&quot;</span><span class="p">),</span>
</span><span id="__span-3-9"><a id="__codelineno-3-9" name="__codelineno-3-9" href="#__codelineno-3-9"></a><span class="w"> </span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;3&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;3&quot;</span><span class="p">),</span>
</span><span id="__span-3-10"><a id="__codelineno-3-10" name="__codelineno-3-10" href="#__codelineno-3-10"></a><span class="w"> </span><span class="p">),</span>
</span><span id="__span-3-11"><a id="__codelineno-3-11" name="__codelineno-3-11" href="#__codelineno-3-11"></a><span class="w"> </span><span class="n">listOf</span><span class="p">(</span>
</span><span id="__span-3-12"><a id="__codelineno-3-12" name="__codelineno-3-12" href="#__codelineno-3-12"></a><span class="w"> </span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;4&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;4&quot;</span><span class="p">),</span>
</span><span id="__span-3-13"><a id="__codelineno-3-13" name="__codelineno-3-13" href="#__codelineno-3-13"></a><span class="w"> </span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;5&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;5&quot;</span><span class="p">),</span>
</span><span id="__span-3-14"><a id="__codelineno-3-14" name="__codelineno-3-14" href="#__codelineno-3-14"></a><span class="w"> </span><span class="p">),</span>
</span><span id="__span-3-15"><a id="__codelineno-3-15" name="__codelineno-3-15" href="#__codelineno-3-15"></a><span class="w"> </span><span class="n">listOf</span><span class="p">(</span>
</span><span id="__span-3-16"><a id="__codelineno-3-16" name="__codelineno-3-16" href="#__codelineno-3-16"></a><span class="w"> </span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;6&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;6&quot;</span><span class="p">),</span>
</span><span id="__span-3-17"><a id="__codelineno-3-17" name="__codelineno-3-17" href="#__codelineno-3-17"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-3-18"><a id="__codelineno-3-18" name="__codelineno-3-18" href="#__codelineno-3-18"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-3-19"><a id="__codelineno-3-19" name="__codelineno-3-19" href="#__codelineno-3-19"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-3-20"><a id="__codelineno-3-20" name="__codelineno-3-20" href="#__codelineno-3-20"></a><span class="p">)</span>
</span></code></pre></div>
<p><img alt="A triangular keyboard" src="keyboards/007.png" title="A triangular keyboard" /></p>
<p>This way of building matrices is not very convenient, so the library provides a few eloquent DSLs to simplify that.</p>
<p>First, there are <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.utils/matrix.html"><code>matrix</code></a> and <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.utils/row.html"><code>row</code></a>, so the keyboard above can be built like this:</p>
<p><div class="language-kotlin highlight"><pre><span></span><code><span id="__span-4-1"><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="n">bot</span><span class="p">.</span><span class="na">sendMessage</span><span class="p">(</span>
</span><span id="__span-4-2"><a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a><span class="w"> </span><span class="n">chatId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">chat</span><span class="p">,</span>
</span><span id="__span-4-3"><a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;DSLs are sweet!&quot;</span><span class="p">,</span>
</span><span id="__span-4-4"><a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a><span class="w"> </span><span class="n">replyMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">InlineKeyboardMarkup</span><span class="p">(</span>
</span><span id="__span-4-5"><a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a><span class="w"> </span><span class="n">keyboard</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">matrix</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-4-6"><a id="__codelineno-4-6" name="__codelineno-4-6" href="#__codelineno-4-6"></a><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-4-7"><a id="__codelineno-4-7" name="__codelineno-4-7" href="#__codelineno-4-7"></a><span class="w"> </span><span class="o">+</span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;1&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;1&quot;</span><span class="p">)</span>
</span><span id="__span-4-8"><a id="__codelineno-4-8" name="__codelineno-4-8" href="#__codelineno-4-8"></a><span class="w"> </span><span class="o">+</span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;2&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;2&quot;</span><span class="p">)</span>
</span><span id="__span-4-9"><a id="__codelineno-4-9" name="__codelineno-4-9" href="#__codelineno-4-9"></a><span class="w"> </span><span class="o">+</span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;3&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;3&quot;</span><span class="p">)</span>
</span><span id="__span-4-10"><a id="__codelineno-4-10" name="__codelineno-4-10" href="#__codelineno-4-10"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-4-11"><a id="__codelineno-4-11" name="__codelineno-4-11" href="#__codelineno-4-11"></a><span class="w"> </span><span class="n">row</span><span class="p">(</span>
</span><span id="__span-4-12"><a id="__codelineno-4-12" name="__codelineno-4-12" href="#__codelineno-4-12"></a><span class="w"> </span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;4&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;4&quot;</span><span class="p">),</span>
</span><span id="__span-4-13"><a id="__codelineno-4-13" name="__codelineno-4-13" href="#__codelineno-4-13"></a><span class="w"> </span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;5&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;5&quot;</span><span class="p">),</span>
</span><span id="__span-4-14"><a id="__codelineno-4-14" name="__codelineno-4-14" href="#__codelineno-4-14"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-4-15"><a id="__codelineno-4-15" name="__codelineno-4-15" href="#__codelineno-4-15"></a><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-4-16"><a id="__codelineno-4-16" name="__codelineno-4-16" href="#__codelineno-4-16"></a><span class="w"> </span><span class="o">+</span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;6&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;6&quot;</span><span class="p">)</span>
</span><span id="__span-4-17"><a id="__codelineno-4-17" name="__codelineno-4-17" href="#__codelineno-4-17"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-4-18"><a id="__codelineno-4-18" name="__codelineno-4-18" href="#__codelineno-4-18"></a><span class="w"> </span><span class="p">},</span>
</span><span id="__span-4-19"><a id="__codelineno-4-19" name="__codelineno-4-19" href="#__codelineno-4-19"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-4-20"><a id="__codelineno-4-20" name="__codelineno-4-20" href="#__codelineno-4-20"></a><span class="p">)</span>
</span></code></pre></div>
</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Those plus signs are mandatory.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>There are two different <code>row</code> functions here. Can you spot the difference?</p>
</div>
<p>A single-row matrix can be built with a <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.utils/flat-matrix.html"><code>flatMatrix</code></a>:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="n">flatMatrix</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a><span class="w"> </span><span class="o">+</span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;1&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;1&quot;</span><span class="p">)</span>
</span><span id="__span-5-3"><a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a><span class="w"> </span><span class="o">+</span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;2&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;2&quot;</span><span class="p">)</span>
</span><span id="__span-5-4"><a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a><span class="w"> </span><span class="o">+</span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;3&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;3&quot;</span><span class="p">)</span>
</span><span id="__span-5-5"><a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a><span class="w"> </span><span class="o">+</span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;4&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;4&quot;</span><span class="p">)</span>
</span><span id="__span-5-6"><a id="__codelineno-5-6" name="__codelineno-5-6" href="#__codelineno-5-6"></a><span class="w"> </span><span class="o">+</span><span class="n">CallbackDataInlineKeyboardButton</span><span class="p">(</span><span class="s">&quot;5&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;5&quot;</span><span class="p">)</span>
</span><span id="__span-5-7"><a id="__codelineno-5-7" name="__codelineno-5-7" href="#__codelineno-5-7"></a><span class="p">}</span>
</span></code></pre></div>
<p>But the most convenient way to build a simple keyboard is to use the constructor-like methods: <a href="https://tgbotapi.inmo.dev/tgbotapi.utils/dev.inmo.tgbotapi.extensions.utils.types.buttons/-inline-keyboard-markup.html"><code>InlineKeyboardMarkup</code></a> and <a href="https://tgbotapi.inmo.dev/tgbotapi.utils/dev.inmo.tgbotapi.extensions.utils.types.buttons/-reply-keyboard-markup.html"><code>ReplyKeyboardMarkup</code></a>.
Note, that they are named just like the corresponding constructor, but take a vararg of buttons.
They create flat matrices, i.e. single rows.</p>
<h3 id="keyboards-dsl">Keyboards DSL<a class="headerlink" href="#keyboards-dsl" title="Permanent link">&para;</a></h3>
<p>Finally, there are <a href="https://tgbotapi.inmo.dev/tgbotapi.utils/dev.inmo.tgbotapi.extensions.utils.types.buttons/inline-keyboard.html"><code>inlineKeyboard</code></a> and <a href="https://tgbotapi.inmo.dev/tgbotapi.utils/dev.inmo.tgbotapi.extensions.utils.types.buttons/reply-keyboard.html"><code>replyKeyboard</code></a></p>
<p>DSL methods above rely on Kotlin&rsquo;s feature of receivers and extensions.
So, the magic is done by <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.utils/-matrix-builder/index.html"><code>MatrixBuilder</code></a> and <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.utils/-row-builder/index.html"><code>RowBuilder</code></a>.
That&rsquo;s why you must use the plus sign to add buttons to the matrix: it&rsquo;s just an overloaded operator call, another cool Kotlin feature widely used to create sweet DSLs.</p>
<p>Another bonus of using these DSLs is button builders, like <a href="https://tgbotapi.inmo.dev/tgbotapi.utils/dev.inmo.tgbotapi.extensions.utils.types.buttons/pay-button.html"><code>payButton</code></a>, <a href="https://tgbotapi.inmo.dev/tgbotapi.utils/dev.inmo.tgbotapi.extensions.utils.types.buttons/data-button.html"><code>dataButton</code></a>, and <a href="https://tgbotapi.inmo.dev/tgbotapi.utils/dev.inmo.tgbotapi.extensions.utils.types.buttons/url-button.html"><code>urlButton</code></a>:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-6-1"><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="n">bot</span><span class="p">.</span><span class="na">sendMessage</span><span class="p">(</span>
</span><span id="__span-6-2"><a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a><span class="w"> </span><span class="n">chatId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">chat</span><span class="p">,</span>
</span><span id="__span-6-3"><a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;All in one!&quot;</span><span class="p">,</span>
</span><span id="__span-6-4"><a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a><span class="w"> </span><span class="n">replyMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">InlineKeyboardMarkup</span><span class="p">(</span>
</span><span id="__span-6-5"><a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a><span class="w"> </span><span class="n">keyboard</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">matrix</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-6-6"><a id="__codelineno-6-6" name="__codelineno-6-6" href="#__codelineno-6-6"></a><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-6-7"><a id="__codelineno-6-7" name="__codelineno-6-7" href="#__codelineno-6-7"></a><span class="w"> </span><span class="n">payButton</span><span class="p">(</span><span class="s">&quot;Send money&quot;</span><span class="p">)</span>
</span><span id="__span-6-8"><a id="__codelineno-6-8" name="__codelineno-6-8" href="#__codelineno-6-8"></a><span class="w"> </span><span class="n">dataButton</span><span class="p">(</span><span class="s">&quot;Ok&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;ok&quot;</span><span class="p">)</span>
</span><span id="__span-6-9"><a id="__codelineno-6-9" name="__codelineno-6-9" href="#__codelineno-6-9"></a><span class="w"> </span><span class="n">urlButton</span><span class="p">(</span><span class="s">&quot;Google&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;https://google.com&quot;</span><span class="p">)</span>
</span><span id="__span-6-10"><a id="__codelineno-6-10" name="__codelineno-6-10" href="#__codelineno-6-10"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-6-11"><a id="__codelineno-6-11" name="__codelineno-6-11" href="#__codelineno-6-11"></a><span class="w"> </span><span class="p">},</span>
</span><span id="__span-6-12"><a id="__codelineno-6-12" name="__codelineno-6-12" href="#__codelineno-6-12"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-6-13"><a id="__codelineno-6-13" name="__codelineno-6-13" href="#__codelineno-6-13"></a><span class="p">)</span>
</span></code></pre></div>
<p>Reply keyboard builders provide similar extensions, e.g.
<a href="https://tgbotapi.inmo.dev/tgbotapi.utils/dev.inmo.tgbotapi.extensions.utils.types.buttons/request-location-button.html"><code>requestLocationButton</code></a>.</p>
<p>So, choose the style you like — from plain Kotlin lists to sweet DSLs — and use it!</p>
<h2 id="working-with-keyboards">Working with keyboards<a class="headerlink" href="#working-with-keyboards" title="Permanent link">&para;</a></h2>
<p>Working with keyboards is not something special in Telegram Bot API.
As you have already seen, keyboards are just message parameters.
Similarly, keyboard interactions are represented by regular <a href="https://core.telegram.org/bots/api#getting-updates">Updates</a>.
I.e. when a user interacts with a keyboard, the bot receives an update.</p>
<p>On the other hand, the library is heavily typed, so the actual type of update you would receive varies.</p>
<h3 id="reply-keyboards">Reply keyboards<a class="headerlink" href="#reply-keyboards" title="Permanent link">&para;</a></h3>
<p>As it was said, reply keyboards cause Telegram clients to send regular messages back to the bot.
Peruse this example:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-7-1"><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="n">bot</span><span class="p">.</span><span class="na">buildBehaviourWithLongPolling</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-7-2"><a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">sendMessage</span><span class="p">(</span>
</span><span id="__span-7-3"><a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a><span class="w"> </span><span class="n">chatId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">chat</span><span class="p">,</span>
</span><span id="__span-7-4"><a id="__codelineno-7-4" name="__codelineno-7-4" href="#__codelineno-7-4"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;👮 Turn in your accomplices or be prepared for a lengthy 🍆 incarceration ⛓ 👊 ‼&quot;</span><span class="p">,</span>
</span><span id="__span-7-5"><a id="__codelineno-7-5" name="__codelineno-7-5" href="#__codelineno-7-5"></a><span class="w"> </span><span class="n">replyMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">replyKeyboard</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-7-6"><a id="__codelineno-7-6" name="__codelineno-7-6" href="#__codelineno-7-6"></a><span class="w"> </span><span class="o">+</span><span class="n">SimpleKeyboardButton</span><span class="p">(</span>
</span><span id="__span-7-7"><a id="__codelineno-7-7" name="__codelineno-7-7" href="#__codelineno-7-7"></a><span class="w"> </span><span class="s">&quot;I ain&#39;t no rat! 🚫🐀🤐🙅&quot;</span>
</span><span id="__span-7-8"><a id="__codelineno-7-8" name="__codelineno-7-8" href="#__codelineno-7-8"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-7-9"><a id="__codelineno-7-9" name="__codelineno-7-9" href="#__codelineno-7-9"></a><span class="w"> </span><span class="o">+</span><span class="n">RequestUserKeyboardButton</span><span class="p">(</span>
</span><span id="__span-7-10"><a id="__codelineno-7-10" name="__codelineno-7-10" href="#__codelineno-7-10"></a><span class="w"> </span><span class="s">&quot;Rat out 🐀 a friend 👤&quot;</span><span class="p">,</span>
</span><span id="__span-7-11"><a id="__codelineno-7-11" name="__codelineno-7-11" href="#__codelineno-7-11"></a><span class="w"> </span><span class="n">KeyboardButtonRequestUser</span><span class="p">.</span><span class="na">Common</span><span class="p">(</span><span class="n">RequestId</span><span class="p">.</span><span class="na">random</span><span class="p">())</span>
</span><span id="__span-7-12"><a id="__codelineno-7-12" name="__codelineno-7-12" href="#__codelineno-7-12"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-7-13"><a id="__codelineno-7-13" name="__codelineno-7-13" href="#__codelineno-7-13"></a><span class="w"> </span><span class="o">+</span><span class="n">RequestChatKeyboardButton</span><span class="p">(</span>
</span><span id="__span-7-14"><a id="__codelineno-7-14" name="__codelineno-7-14" href="#__codelineno-7-14"></a><span class="w"> </span><span class="s">&quot;Rat out 🐀 a group of friends 👥&quot;</span><span class="p">,</span>
</span><span id="__span-7-15"><a id="__codelineno-7-15" name="__codelineno-7-15" href="#__codelineno-7-15"></a><span class="w"> </span><span class="n">KeyboardButtonRequestChat</span><span class="p">.</span><span class="na">Group</span><span class="p">(</span><span class="n">RequestId</span><span class="p">.</span><span class="na">random</span><span class="p">())</span>
</span><span id="__span-7-16"><a id="__codelineno-7-16" name="__codelineno-7-16" href="#__codelineno-7-16"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-7-17"><a id="__codelineno-7-17" name="__codelineno-7-17" href="#__codelineno-7-17"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-7-18"><a id="__codelineno-7-18" name="__codelineno-7-18" href="#__codelineno-7-18"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-7-19"><a id="__codelineno-7-19" name="__codelineno-7-19" href="#__codelineno-7-19"></a>
</span><span id="__span-7-20"><a id="__codelineno-7-20" name="__codelineno-7-20" href="#__codelineno-7-20"></a><span class="w"> </span><span class="n">onText</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">message</span><span class="p">:</span><span class="w"> </span><span class="n">CommonMessage</span><span class="o">&lt;</span><span class="n">TextContent</span><span class="o">&gt;</span><span class="w"> </span><span class="o">-&gt;</span>
</span><span id="__span-7-21"><a id="__codelineno-7-21" name="__codelineno-7-21" href="#__codelineno-7-21"></a><span class="w"> </span><span class="n">assert</span><span class="p">(</span><span class="n">message</span><span class="p">.</span><span class="na">text</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s">&quot;I ain&#39;t no rat! 🚫🐀🤐🙅&quot;</span><span class="p">)</span>
</span><span id="__span-7-22"><a id="__codelineno-7-22" name="__codelineno-7-22" href="#__codelineno-7-22"></a><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">reply</span><span class="p">(</span>
</span><span id="__span-7-23"><a id="__codelineno-7-23" name="__codelineno-7-23" href="#__codelineno-7-23"></a><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">message</span><span class="p">,</span>
</span><span id="__span-7-24"><a id="__codelineno-7-24" name="__codelineno-7-24" href="#__codelineno-7-24"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;Good, you&#39;re going to jail alone! ⛓🧑⛓&quot;</span><span class="p">,</span>
</span><span id="__span-7-25"><a id="__codelineno-7-25" name="__codelineno-7-25" href="#__codelineno-7-25"></a><span class="w"> </span><span class="n">replyMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ReplyKeyboardRemove</span><span class="p">()</span>
</span><span id="__span-7-26"><a id="__codelineno-7-26" name="__codelineno-7-26" href="#__codelineno-7-26"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-7-27"><a id="__codelineno-7-27" name="__codelineno-7-27" href="#__codelineno-7-27"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-7-28"><a id="__codelineno-7-28" name="__codelineno-7-28" href="#__codelineno-7-28"></a>
</span><span id="__span-7-29"><a id="__codelineno-7-29" name="__codelineno-7-29" href="#__codelineno-7-29"></a><span class="w"> </span><span class="n">onUserShared</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">message</span><span class="p">:</span><span class="w"> </span><span class="n">PrivateEventMessage</span><span class="o">&lt;</span><span class="n">UserShared</span><span class="o">&gt;</span><span class="w"> </span><span class="o">-&gt;</span>
</span><span id="__span-7-30"><a id="__codelineno-7-30" name="__codelineno-7-30" href="#__codelineno-7-30"></a><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">reply</span><span class="p">(</span>
</span><span id="__span-7-31"><a id="__codelineno-7-31" name="__codelineno-7-31" href="#__codelineno-7-31"></a><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">message</span><span class="p">,</span>
</span><span id="__span-7-32"><a id="__codelineno-7-32" name="__codelineno-7-32" href="#__codelineno-7-32"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;Haha, you and you friend are both going to jail! ⛓👬⛓&quot;</span><span class="p">,</span>
</span><span id="__span-7-33"><a id="__codelineno-7-33" name="__codelineno-7-33" href="#__codelineno-7-33"></a><span class="w"> </span><span class="n">replyMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ReplyKeyboardRemove</span><span class="p">()</span>
</span><span id="__span-7-34"><a id="__codelineno-7-34" name="__codelineno-7-34" href="#__codelineno-7-34"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-7-35"><a id="__codelineno-7-35" name="__codelineno-7-35" href="#__codelineno-7-35"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-7-36"><a id="__codelineno-7-36" name="__codelineno-7-36" href="#__codelineno-7-36"></a>
</span><span id="__span-7-37"><a id="__codelineno-7-37" name="__codelineno-7-37" href="#__codelineno-7-37"></a><span class="w"> </span><span class="n">onChatShared</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">message</span><span class="p">:</span><span class="w"> </span><span class="n">PrivateEventMessage</span><span class="o">&lt;</span><span class="n">ChatShared</span><span class="o">&gt;</span><span class="w"> </span><span class="o">-&gt;</span>
</span><span id="__span-7-38"><a id="__codelineno-7-38" name="__codelineno-7-38" href="#__codelineno-7-38"></a><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">reply</span><span class="p">(</span>
</span><span id="__span-7-39"><a id="__codelineno-7-39" name="__codelineno-7-39" href="#__codelineno-7-39"></a><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">message</span><span class="p">,</span>
</span><span id="__span-7-40"><a id="__codelineno-7-40" name="__codelineno-7-40" href="#__codelineno-7-40"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;Haha, now you&#39;re all going to jail! ⛓👨‍👦‍👦⛓&quot;</span><span class="p">,</span>
</span><span id="__span-7-41"><a id="__codelineno-7-41" name="__codelineno-7-41" href="#__codelineno-7-41"></a><span class="w"> </span><span class="n">replyMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ReplyKeyboardRemove</span><span class="p">()</span>
</span><span id="__span-7-42"><a id="__codelineno-7-42" name="__codelineno-7-42" href="#__codelineno-7-42"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-7-43"><a id="__codelineno-7-43" name="__codelineno-7-43" href="#__codelineno-7-43"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-7-44"><a id="__codelineno-7-44" name="__codelineno-7-44" href="#__codelineno-7-44"></a><span class="p">}.</span><span class="na">join</span><span class="p">()</span>
</span></code></pre></div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Read more about <code>buildBehaviourWithLongPolling</code> <a href="../logic/behaviour-builder.html">here</a></p>
</div>
<p>I hope you get the idea: the bot acts like a cop and asks the user to rat out his friends via a reply keyboard (it&rsquo;s an imaginary situation, of course).
The user may refuse to cooperate, rat out a single friend or the whole imaginary group.
The bot receives the user&rsquo;s choices as regular updates, the code above has explicit types (generally optional in Kotlin) and an assert to demonstrate this.</p>
<p>And here is how it works (the user selects the options in the order):</p>
<video src='keyboards/008.mp4' width="100%"></video>
<!-- ![Reply keyboards](keyboards/008.gif "Reply keyboards") -->
<p>Note how you handle reply keyboards: you process regular messages.
For instance, a simple text button sends a regular text message indistinguishable from a case when a user simply types the same text manually.</p>
<p>And don&rsquo;t be a rat in real life: remove the keyboards with the <code>ReplyKeyboardRemove</code> after you&rsquo;ve received the input!
Otherwise, a keyboard will stay there indefinitely.</p>
<h3 id="inline-keyboards">Inline keyboards<a class="headerlink" href="#inline-keyboards" title="Permanent link">&para;</a></h3>
<p>Finally, to master the keyboards, you need to know how to handle the inline ones.</p>
<p>Again, let&rsquo;s explore the example.
Imagine you&rsquo;re making a quiz where users are given a question and a set of answers.
Additionally, users are given a link to the wiki page to help with the question and a Google button.</p>
<p>The quiz could be implemented this way:</p>
<div class="language-kotlin highlight"><pre><span></span><code><span id="__span-8-1"><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="c1">// A simple data class to represent a question</span>
</span><span id="__span-8-2"><a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a><span class="kd">val</span><span class="w"> </span><span class="nv">question</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Question</span><span class="p">(</span>
</span><span id="__span-8-3"><a id="__codelineno-8-3" name="__codelineno-8-3" href="#__codelineno-8-3"></a><span class="w"> </span><span class="n">image</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;https://upload.wikimedia.org/wikipedia/commons/a/a5/Tsunami_by_hokusai_19th_century.jpg&quot;</span><span class="p">,</span>
</span><span id="__span-8-4"><a id="__codelineno-8-4" name="__codelineno-8-4" href="#__codelineno-8-4"></a><span class="w"> </span><span class="n">question</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;Who painted this?&quot;</span><span class="p">,</span>
</span><span id="__span-8-5"><a id="__codelineno-8-5" name="__codelineno-8-5" href="#__codelineno-8-5"></a><span class="w"> </span><span class="n">answers</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">listOf</span><span class="p">(</span>
</span><span id="__span-8-6"><a id="__codelineno-8-6" name="__codelineno-8-6" href="#__codelineno-8-6"></a><span class="w"> </span><span class="n">Answer</span><span class="p">(</span><span class="s">&quot;Hokusai&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">correct</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">),</span>
</span><span id="__span-8-7"><a id="__codelineno-8-7" name="__codelineno-8-7" href="#__codelineno-8-7"></a><span class="w"> </span><span class="n">Answer</span><span class="p">(</span><span class="s">&quot;Sukenobu&quot;</span><span class="p">),</span>
</span><span id="__span-8-8"><a id="__codelineno-8-8" name="__codelineno-8-8" href="#__codelineno-8-8"></a><span class="w"> </span><span class="n">Answer</span><span class="p">(</span><span class="s">&quot;Chōshun&quot;</span><span class="p">),</span>
</span><span id="__span-8-9"><a id="__codelineno-8-9" name="__codelineno-8-9" href="#__codelineno-8-9"></a><span class="w"> </span><span class="n">Answer</span><span class="p">(</span><span class="s">&quot;Kiyonobu I&quot;</span><span class="p">),</span>
</span><span id="__span-8-10"><a id="__codelineno-8-10" name="__codelineno-8-10" href="#__codelineno-8-10"></a><span class="w"> </span><span class="p">),</span>
</span><span id="__span-8-11"><a id="__codelineno-8-11" name="__codelineno-8-11" href="#__codelineno-8-11"></a><span class="w"> </span><span class="n">wiki</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;https://en.wikipedia.org/wiki/Ukiyo-e&quot;</span><span class="p">,</span>
</span><span id="__span-8-12"><a id="__codelineno-8-12" name="__codelineno-8-12" href="#__codelineno-8-12"></a><span class="p">)</span>
</span><span id="__span-8-13"><a id="__codelineno-8-13" name="__codelineno-8-13" href="#__codelineno-8-13"></a>
</span><span id="__span-8-14"><a id="__codelineno-8-14" name="__codelineno-8-14" href="#__codelineno-8-14"></a><span class="n">bot</span><span class="p">.</span><span class="na">buildBehaviourWithLongPolling</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-8-15"><a id="__codelineno-8-15" name="__codelineno-8-15" href="#__codelineno-8-15"></a><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">sendPhoto</span><span class="p">(</span>
</span><span id="__span-8-16"><a id="__codelineno-8-16" name="__codelineno-8-16" href="#__codelineno-8-16"></a><span class="w"> </span><span class="n">chatId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">chat</span><span class="p">,</span>
</span><span id="__span-8-17"><a id="__codelineno-8-17" name="__codelineno-8-17" href="#__codelineno-8-17"></a><span class="w"> </span><span class="n">fileId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">InputFile</span><span class="p">.</span><span class="na">fromUrl</span><span class="p">(</span><span class="n">question</span><span class="p">.</span><span class="na">image</span><span class="p">),</span>
</span><span id="__span-8-18"><a id="__codelineno-8-18" name="__codelineno-8-18" href="#__codelineno-8-18"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">question</span><span class="p">.</span><span class="na">question</span><span class="p">,</span>
</span><span id="__span-8-19"><a id="__codelineno-8-19" name="__codelineno-8-19" href="#__codelineno-8-19"></a><span class="w"> </span><span class="n">replyMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">inlineKeyboard</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-8-20"><a id="__codelineno-8-20" name="__codelineno-8-20" href="#__codelineno-8-20"></a><span class="w"> </span><span class="c1">// First row: answers</span>
</span><span id="__span-8-21"><a id="__codelineno-8-21" name="__codelineno-8-21" href="#__codelineno-8-21"></a><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-8-22"><a id="__codelineno-8-22" name="__codelineno-8-22" href="#__codelineno-8-22"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">answer</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">question</span><span class="p">.</span><span class="na">answers</span><span class="p">.</span><span class="na">shuffled</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-8-23"><a id="__codelineno-8-23" name="__codelineno-8-23" href="#__codelineno-8-23"></a><span class="w"> </span><span class="n">dataButton</span><span class="p">(</span>
</span><span id="__span-8-24"><a id="__codelineno-8-24" name="__codelineno-8-24" href="#__codelineno-8-24"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer</span><span class="p">.</span><span class="na">answer</span><span class="p">,</span>
</span><span id="__span-8-25"><a id="__codelineno-8-25" name="__codelineno-8-25" href="#__codelineno-8-25"></a><span class="w"> </span><span class="n">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;</span><span class="si">${</span><span class="n">answer</span><span class="p">.</span><span class="na">answer</span><span class="si">}</span><span class="s">:</span><span class="si">${</span><span class="n">answer</span><span class="p">.</span><span class="na">correct</span><span class="si">}</span><span class="s">&quot;</span><span class="p">,</span>
</span><span id="__span-8-26"><a id="__codelineno-8-26" name="__codelineno-8-26" href="#__codelineno-8-26"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-8-27"><a id="__codelineno-8-27" name="__codelineno-8-27" href="#__codelineno-8-27"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-8-28"><a id="__codelineno-8-28" name="__codelineno-8-28" href="#__codelineno-8-28"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-8-29"><a id="__codelineno-8-29" name="__codelineno-8-29" href="#__codelineno-8-29"></a>
</span><span id="__span-8-30"><a id="__codelineno-8-30" name="__codelineno-8-30" href="#__codelineno-8-30"></a><span class="w"> </span><span class="c1">// Second row: help buttons</span>
</span><span id="__span-8-31"><a id="__codelineno-8-31" name="__codelineno-8-31" href="#__codelineno-8-31"></a><span class="w"> </span><span class="n">row</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-8-32"><a id="__codelineno-8-32" name="__codelineno-8-32" href="#__codelineno-8-32"></a><span class="w"> </span><span class="n">urlButton</span><span class="p">(</span><span class="s">&quot;Wiki 💁&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">question</span><span class="p">.</span><span class="na">wiki</span><span class="p">)</span>
</span><span id="__span-8-33"><a id="__codelineno-8-33" name="__codelineno-8-33" href="#__codelineno-8-33"></a><span class="w"> </span><span class="n">webAppButton</span><span class="p">(</span><span class="s">&quot;Google 🔍&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;https://google.com&quot;</span><span class="p">)</span>
</span><span id="__span-8-34"><a id="__codelineno-8-34" name="__codelineno-8-34" href="#__codelineno-8-34"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-8-35"><a id="__codelineno-8-35" name="__codelineno-8-35" href="#__codelineno-8-35"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-8-36"><a id="__codelineno-8-36" name="__codelineno-8-36" href="#__codelineno-8-36"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-8-37"><a id="__codelineno-8-37" name="__codelineno-8-37" href="#__codelineno-8-37"></a>
</span><span id="__span-8-38"><a id="__codelineno-8-38" name="__codelineno-8-38" href="#__codelineno-8-38"></a><span class="w"> </span><span class="n">onDataCallbackQuery</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">callback</span><span class="p">:</span><span class="w"> </span><span class="n">DataCallbackQuery</span><span class="w"> </span><span class="o">-&gt;</span>
</span><span id="__span-8-39"><a id="__codelineno-8-39" name="__codelineno-8-39" href="#__codelineno-8-39"></a><span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="p">(</span><span class="nv">answer</span><span class="p">,</span><span class="w"> </span><span class="nv">correct</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">callback</span><span class="p">.</span><span class="na">data</span><span class="p">.</span><span class="na">split</span><span class="p">(</span><span class="s">&quot;:&quot;</span><span class="p">)</span>
</span><span id="__span-8-40"><a id="__codelineno-8-40" name="__codelineno-8-40" href="#__codelineno-8-40"></a>
</span><span id="__span-8-41"><a id="__codelineno-8-41" name="__codelineno-8-41" href="#__codelineno-8-41"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">correct</span><span class="p">.</span><span class="na">toBoolean</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-8-42"><a id="__codelineno-8-42" name="__codelineno-8-42" href="#__codelineno-8-42"></a><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">answerCallbackQuery</span><span class="p">(</span>
</span><span id="__span-8-43"><a id="__codelineno-8-43" name="__codelineno-8-43" href="#__codelineno-8-43"></a><span class="w"> </span><span class="n">callback</span><span class="p">,</span>
</span><span id="__span-8-44"><a id="__codelineno-8-44" name="__codelineno-8-44" href="#__codelineno-8-44"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;</span><span class="si">$</span><span class="n">answer</span><span class="s"> is a ✅ correct answer!&quot;</span><span class="p">,</span>
</span><span id="__span-8-45"><a id="__codelineno-8-45" name="__codelineno-8-45" href="#__codelineno-8-45"></a><span class="w"> </span><span class="n">showAlert</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span>
</span><span id="__span-8-46"><a id="__codelineno-8-46" name="__codelineno-8-46" href="#__codelineno-8-46"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-8-47"><a id="__codelineno-8-47" name="__codelineno-8-47" href="#__codelineno-8-47"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
</span><span id="__span-8-48"><a id="__codelineno-8-48" name="__codelineno-8-48" href="#__codelineno-8-48"></a><span class="w"> </span><span class="n">bot</span><span class="p">.</span><span class="na">answerCallbackQuery</span><span class="p">(</span>
</span><span id="__span-8-49"><a id="__codelineno-8-49" name="__codelineno-8-49" href="#__codelineno-8-49"></a><span class="w"> </span><span class="n">callback</span><span class="p">,</span>
</span><span id="__span-8-50"><a id="__codelineno-8-50" name="__codelineno-8-50" href="#__codelineno-8-50"></a><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;❌ Try again, </span><span class="si">$</span><span class="n">answer</span><span class="s"> is not a correct answer…&quot;</span><span class="p">,</span>
</span><span id="__span-8-51"><a id="__codelineno-8-51" name="__codelineno-8-51" href="#__codelineno-8-51"></a><span class="w"> </span><span class="n">showAlert</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span>
</span><span id="__span-8-52"><a id="__codelineno-8-52" name="__codelineno-8-52" href="#__codelineno-8-52"></a><span class="w"> </span><span class="p">)</span>
</span><span id="__span-8-53"><a id="__codelineno-8-53" name="__codelineno-8-53" href="#__codelineno-8-53"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-8-54"><a id="__codelineno-8-54" name="__codelineno-8-54" href="#__codelineno-8-54"></a><span class="w"> </span><span class="p">}</span>
</span><span id="__span-8-55"><a id="__codelineno-8-55" name="__codelineno-8-55" href="#__codelineno-8-55"></a><span class="p">}.</span><span class="na">join</span><span class="p">()</span>
</span></code></pre></div>
<p>A few important things to note here.</p>
<p>First, the data buttons (they have the <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons/-callback-data-inline-keyboard-button/index.html"><code>CallbackDataInlineKeyboardButton</code></a> type, but in the code we used a <a href="https://tgbotapi.inmo.dev/tgbotapi.utils/dev.inmo.tgbotapi.extensions.utils.types.buttons/data-button.html">neat DSL</a>) must have unique <code>data</code>.
If the <code>data</code> is not unique, Telegram clients will highlight all the buttons with the same data when a user clicks on one of them.
Guess how I know that?
Well, it&rsquo;s not in the docs, so trial and error is the only way to learn it (and many other things about the Telegram Bot API).</p>
<p>Second, the way you handle inline keyboards is different from the way you handle reply keyboards.
Bot API will send updates with a <code>callback_query</code> field populated.
This field, of a <a href="https://core.telegram.org/bots/api#callbackquery"><code>CallbackQuery</code></a> type, represents incoming callbacks from callback buttons in inline keyboards.
The library turns them into <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.types.queries.callback/index.html">multiple callback types</a>, like the <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.types.queries.callback/-data-callback-query/index.html"><code>DataCallbackQuery</code></a> we used in the example.
Finally, to handle these callbacks you could use <a href="https://tgbotapi.inmo.dev/tgbotapi.behaviour_builder/dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling/on-data-callback-query.html"><code>onDataCallbackQuery</code></a>.
Alternatively, if you&rsquo;re not using any DSLs, you have to handle the <a href="https://tgbotapi.inmo.dev/tgbotapi.core/dev.inmo.tgbotapi.types.update/-callback-query-update/index.html"><code>CallbackQueryUpdate</code></a> update type.</p>
<p>Third, the buttons got highlighted when a user clicks on them.
When you&rsquo;re done with the callback, you need to answer it, by using the <a href="https://tgbotapi.inmo.dev/tgbotapi.api/dev.inmo.tgbotapi.extensions.api.answers/answer-callback-query.html"><code>answerCallbackQuery</code></a> function.
Otherwise, the button will remain highlighted.
Telegram clients will eventually remove the highlight, but it&rsquo;s still frustrating.</p>
<p>Finally, you could choose between two styles of acknowledgment: a simple toast-like message or a modal alert.
The <code>showAlert</code> flag controls this behavior.</p>
<p>And here is the demo of the quiz:</p>
<video src='keyboards/009.mp4' width="100%"></video>
<!-- ![Inline keyboards](keyboards/009.gif "Inline keyboards") -->
<h2 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Permanent link">&para;</a></h2>
<p>Today we&rsquo;ve learned how to use keyboards in Telegram bots.
There are two types of keyboards: reply and inline.
Reply keyboards replace the device&rsquo;s keyboard and make clients send a message with the predefined content.
Inline keyboards are buttons attached to messages.
Clicking on them causes the client to send a callback to the bot.
In both scenarios the bot receives an update of a corresponding type and has to acknowledge the keayboard interaction for the client to work properly.</p>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12Z"/></svg>
Back to top
</button>
</main>
<footer class="md-footer">
<nav class="md-footer__inner md-grid" aria-label="Footer" >
<a href="../introduction/first-bot.html" class="md-footer__link md-footer__link--prev" aria-label="Previous: First bot">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
<div class="md-footer__title">
<span class="md-footer__direction">
Previous
</span>
<div class="md-ellipsis">
First bot
</div>
</div>
</a>
<a href="../updates/updates-filters.html" class="md-footer__link md-footer__link--next" aria-label="Next: Updates filters">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Updates filters
</div>
</div>
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"/></svg>
</div>
</a>
</nav>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
<div class="md-social">
<a href="https://github.com/InsanusMokrassar" target="_blank" rel="noopener" title="github.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</a>
<a href="https://hub.docker.com/r/insanusmokrassar" target="_blank" rel="noopener" title="hub.docker.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M349.9 236.3h-66.1v-59.4h66.1v59.4zm0-204.3h-66.1v60.7h66.1V32zm78.2 144.8H362v59.4h66.1v-59.4zm-156.3-72.1h-66.1v60.1h66.1v-60.1zm78.1 0h-66.1v60.1h66.1v-60.1zm276.8 100c-14.4-9.7-47.6-13.2-73.1-8.4-3.3-24-16.7-44.9-41.1-63.7l-14-9.3-9.3 14c-18.4 27.8-23.4 73.6-3.7 103.8-8.7 4.7-25.8 11.1-48.4 10.7H2.4c-8.7 50.8 5.8 116.8 44 162.1 37.1 43.9 92.7 66.2 165.4 66.2 157.4 0 273.9-72.5 328.4-204.2 21.4.4 67.6.1 91.3-45.2 1.5-2.5 6.6-13.2 8.5-17.1l-13.3-8.9zm-511.1-27.9h-66v59.4h66.1v-59.4zm78.1 0h-66.1v59.4h66.1v-59.4zm78.1 0h-66.1v59.4h66.1v-59.4zm-78.1-72.1h-66.1v60.1h66.1v-60.1z"/></svg>
</a>
<a href="https://t.me/InsanusMokrassar" target="_blank" rel="noopener" title="t.me" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M248 8C111.033 8 0 119.033 0 256s111.033 248 248 248 248-111.033 248-248S384.967 8 248 8Zm114.952 168.66c-3.732 39.215-19.881 134.378-28.1 178.3-3.476 18.584-10.322 24.816-16.948 25.425-14.4 1.326-25.338-9.517-39.287-18.661-21.827-14.308-34.158-23.215-55.346-37.177-24.485-16.135-8.612-25 5.342-39.5 3.652-3.793 67.107-61.51 68.335-66.746.153-.655.3-3.1-1.154-4.384s-3.59-.849-5.135-.5q-3.283.746-104.608 69.142-14.845 10.194-26.894 9.934c-8.855-.191-25.888-5.006-38.551-9.123-15.531-5.048-27.875-7.717-26.8-16.291q.84-6.7 18.45-13.7 108.446-47.248 144.628-62.3c68.872-28.647 83.183-33.623 92.511-33.789 2.052-.034 6.639.474 9.61 2.885a10.452 10.452 0 0 1 3.53 6.716 43.765 43.765 0 0 1 .417 9.769Z"/></svg>
</a>
<a href="https://twitter.com/InsanusMokrassa" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.footer", "navigation.indexes", "navigation.sections", "navigation.tabs", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../assets/javascripts/workers/search.b8dbb3d2.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../../assets/javascripts/bundle.c8d2eff1.min.js"></script>
</body>
</html>