Telegram messenger channel
Allows to create chatbots for Telegram.
Built on top of Kotlin Telegram Bot library.
How to use
1. Include Telegram dependency to your build.gradle
implementation("com.just-ai.jaicf:telegram:$jaicfVersion")
Replace $jaicfVersion
with the latest version
Also add Jitpack to repositories:
repositories {
mavenCentral()
jcenter()
maven(uri("https://jitpack.io"))
}
2. Use Telegram request
and reactions
in your scenarios’ actions
action {
// Telegram incoming message
val message = request.telegram?.message
// Fetch username
val username = message?.chat?.username
// Use Telegram-specified response builders
reactions.telegram?.say("Are you agree?", listOf("Yes", "No"))
reactions.telegram?.image("https://address.com/image.jpg", "Image caption")
reactions.telegram?.api?.sendAudio(message?.chat?.id, File("audio.mp3"))
// Or use standard response builders
reactions.say("Hello there!")
reactions.image("https://address.com/image.jpg")
}
Note that Telegram bot works as long polling. This means that every reactions’ method actually sends a response to the user.
Refer to the TelegramReactions class to learn more about available response builders.
Native API
You can use native Telegram API directly via reactions.telegram?.api
. This enables you to build any response that Telegram supports using channel-specific features. As well as fetch some data from Telegram bot API (like getMe for example).
action {
val me = reactions.telegram?.run {
api.getMe().first?.body()?.result
}
}
Learn more about available API methods here.
3. Create a new bot in Telegram
Create a new bot using Telegram’s @BotFather
and any Telegram client as described here. Copy your new bot’s access token to the clipboard.
4. Create and run Telegram channel
Using JAICP
For local development:
fun main() {
JaicpPollingConnector(
botApi = helloWorldBot,
accessToken = "your JAICF project token",
channels = listOf(
TelegramChannel
)
).runBlocking()
}
For cloud production:
fun main() {
JaicpServer(
botApi = helloWorldBot,
accessToken = "your JAICF project token",
channels = listOf(
TelegramChannel
)
).start(wait = true)
}
Or locally:
fun main() {
TelegramChannel(helloWorldBot, "access token").run()
}
Commands
Telegram enables users not only to send a text queries or use buttons. It also provides an ability to send commands that start from slash.
The most known command of the Telegram is “/start” that is sending once the user starts using your chatbot. Your scenario must handle this command via regex activator to react on the first user’s request.
val HelloWorldScenario = Scenario {
state("main") {
activators {
regex("/start")
}
action {
reactions.say("Hello there!")
}
}
}
To make it work, just add RegexActivator
to the array of activators in your agent’s configuration:
val helloWorldBot = BotEngine(
scenario = HelloWorldScenario,
activators = arrayOf(
RegexActivator,
CatchAllActivator
)
)
The same way you can react on ony other Telegram commands.
Events
User can send not only a text queries to your Telegram bot. They can also send contacts and locations for example. These messages contain non-text queries and can be handled in your scenarios via event
activators.
state("events") {
activators {
event(TelegramEvent.LOCATION)
event(TelegramEvent.CONTACT)
}
action {
val location = request.telegram?.location
val contact = request.telegram?.contact
}
}
Buttons
Telegram allows to add keyboard or inline keyboard to the text message reply. This means that it’s not possible to add a keyboard without an actual text response.
action {
reactions.say("Click on the button below")
reactions.buttons("Click me", "Or me")
}
This code generates inline keyboard right below the text “Click on the button below”. Once the user clicks on any of these buttons, the title of the clicked one returns to the bot as a new query.
To add any keyboard to the response, you can use a channel-specific methods:
action {
// Append inline keyboard
reactions.telegram?.say("Are you agree?", listOf("Yes", "No"))
// Append arbitrary keyboard layout
reactions.telegram?.say(
"Could you please send me your contact?",
replyMarkup = KeyboardReplyMarkup(
listOf(listOf(KeyboardButton("Send", requestContact = true), KeyboardButton("No")))
)
)
}
You can also remove keyboard sending a ReplyKeyboardRemove
in the response:
action {
reactions.telegram?.say("Okay then!", replyMarkup = ReplyKeyboardRemove())
}
Refer to the TelegramReactions class to learn more about buttons replies.
Payments
You can accept payments for services or goods you provide from Telegram users. To do this, you need to connect a payment system and obtain its unique token.
action {
val info = PaymentInvoiceInfo(
"title",
"description",
"unique payload",
"381964478:TEST:67912",
"unique-start-parameter",
"USD",
listOf(LabeledPrice("price", BigInteger.valueOf(20_00)))
)
reactions.telegram?.sendInvoice(info)
}
To learn about available currencies and more, you can read the telegram payment documentation.
Goods availability
Before proceeding with the payment, Telegram sends a request to bot to check the goods availability. This request triggers preCheckout event in scenario. Add the preCheckout as a top level state.
Note that when paying in group chats, payment confirmation is sent to the user who sent the payment request, not the entire chat. So there will be created a separate context for the user. If the user communicates with the user in a personal chat the context remains the same.
state("preCheckout") {
activators {
event(TelegramEvent.PRE_CHECKOUT)
}
action(telegram.preCheckout) {
reactions.answerPreCheckoutQuery(request.preCheckoutQuery.id, true)
}
}
You always need to handle the telegramPreCheckout event in the script. Otherwise payments will fail, and all subsequent user messages will be handled in the CatchAll state.
Also you can handle successfulPayment event inside nested states in the TelegramPayment state
state("successfulPayment") {
activators {
event(TelegramEvent.SUCCESSFUL_PAYMENT)
}
action(telegram.successfulPayment) {
reactions.say("We are glad you bought from us")
}
}