Skip to content

baderouaich/tgbotxx

Repository files navigation

MIT License Docs Language

tgbotxx

Telegram Bot C++ Library

Compatible with Telegram Bot API 6.9 (September 22, 2023)

CI Status

Operating system Build status
Ubuntu (x64) Ubuntu
Windows (x64) Windows
macOS macOS

Examples

see examples for more

Example Description Preview
WeatherBot Bot that displays the weather information of a city using the weather api. preview
EarthquakeBot Bot that will alert you if there is a recent earthquake somewhere in the world. preview
QrCodeBot Bot that can generate QrCode images from text and extract text from QrCode Images. preview
UrlShortenerBot Bot for shortening URLs. preview
Inline Buttons Bot that uses inline keyboard buttons to interact with users. preview
Keyboard Buttons Bot that uses keyboard buttons to interact with users. preview
PaidSubscriptionBot Bot that offers it's services for a paid subscription. preview
ThreadPoolBot Bot that uses a ThreadPool to handle multiple requests simultaneously. preview
GitWatcherBot Real world Bot that you can use to watch repositories changes and get notified about (stars, forks, issues, watchers and pulls). preview

Basic sample

see examples for more

#include <tgbotxx/tgbotxx.hpp>
#include <iostream>
using namespace tgbotxx;

class MyBot : public Bot {
public:
  MyBot() : Bot("BOT_TOKEN_FROM_BOT_FATHER") {}
    
private:
  void onStart() override {
    // Called before Bot starts receiving updates
    // Initialize your code here...
    std::cout << "Bot Started\n";
  }
  void onStop() override {
    // Called before Bot shuts down (triggered by Bot::stop())
    // Cleanup your code here
    std::cout << "Bot Stopped\n";
  }
  void onAnyMessage(const Ptr<Message>& message) override {
    // Called when Bot receives a new message of any kind
    // NB: a Ptr<T> is just an alias to std::shared_ptr<T>
    api()->sendMessage(message->chat->id, "Hi " + message->from->firstName + "!, got your message!");
  }
  // override other callbacks if needed... 
};

int main() {
  MyBot bot;
  bot.start();
  return 0;
}

Extensive sample

Creating a new Bot called MyBot that overrides all callbacks:

Show
#include <tgbotxx/tgbotxx.hpp>
#include <iostream>
using namespace tgbotxx;

class MyBot : public Bot {
public:
    MyBot() : Bot("BOT_TOKEN_FROM_BOT_FATHER") {}

private:
    /// Called before Bot starts receiving updates (triggered by Bot::start())
    /// Use this callback to initialize your code, set commands..
    void onStart() override {
      // Drop awaiting updates (when Bot is not running, updates will remain 24 hours
      // in Telegram server before they get deleted or retrieved by BOT)
      api()->deleteWebhook(true);

      // Register bot commands ...
      Ptr<BotCommand> greet(new BotCommand());
      greet->command = "greet";
      greet->description = "This command will greet you";
      Ptr<BotCommand> stop(new BotCommand());
      stop->command = "stop";
      stop->description = "Stop the bot";
      api()->setMyCommands({greet, stop}); // The above commands will be shown in the bot chat menu (bottom left)
      
      std::cout << "Bot " << api()->getMe()->username << " Started\n";
    }
    
    /// Called when Bot is about to be stopped (triggered by Bot::stop())
    void onStop() override {
      /// Cleanup your code in this callback (close handles, backup data...)
      std::cout << "Bot " << api()->getMe()->username << " Stopped\n";
    }
    
    /// Called when a new message is received of any kind - text, photo, sticker, etc.
    void onAnyMessage(const Ptr<Message>& message) override {
        api()->sendMessage(message->chat->id, "Hi " + message->from->firstName + "!, got your message!");
    }
    
    /// Called when a new command is received (messages with leading '/' char).
    void onCommand(const Ptr<Message>& message) override {
      if(message->text == "/stop") {
        api()->sendMessage(message->chat->id, "Bot stopping...");
        Bot::stop();
        return;
      }
    }
    
    /// Called when long polling fails
    void onLongPollError(const std::string& errorMessage, ErrorCode errorCode) override {
      std::cerr <<  "Long polling error: " << errorMessage << ". Error code: " << errorCode << std::endl;
    }
    
    /// @brief Called when a non-command message is received of any kind - text, photo, sticker, etc.
    void onNonCommandMessage(const Ptr<Message>& message) override {}
    
    /// @brief Called when an unknown command is received (messages with leading '/' char).
    /// @note Known commands are set with Bot::setCommands()
    void onUnknownCommand(const Ptr<Message>& message) override {}

    /// @brief Called when a new version of a message that is known to the bot and was edited
    void onEditedMessage(const Ptr<Message>& editedMessage) override {}

    /// @brief Called when a reaction to a message was changed by a user.
    /// @note The bot must be an administrator in the chat and must explicitly specify "message_reaction" in the list of allowed_updates to receive these updates using Api::setAllowedUpdates().
    /// The update isn't received for reactions set by bots.
    void onMessageReactionUpdated(const Ptr<MessageReactionUpdated>& messageReaction) override {}

    /// @brief Called when reactions to a message with anonymous reactions were changed.
    /// @note The bot must be an administrator in the chat and must explicitly specify "message_reaction_count" in the list of allowed_updates to receive these updates using Api::setAllowedUpdates().
    /// The updates are grouped and can be sent with delay up to a few minutes.
    void onMessageReactionCountUpdated(const Ptr<MessageReactionCountUpdated>& messageReactionCount) override {}

    /// @brief Called when a new incoming inline query is received
    void onInlineQuery(const Ptr<InlineQuery>& inlineQuery) override {}

    /// @brief Called when the result of an inline query that was chosen by a user and sent to their chat partner.
    /// @note Please see our documentation on the feedback collecting for details on how to enable these updates for your bot. https://core.telegram.org/bots/inline#collecting-feedback
    void onChosenInlineResult(const Ptr<ChosenInlineResult>& chosenInlineResult) override {}

    /// @brief Called when a new incoming callback query is received
    void onCallbackQuery(const Ptr<CallbackQuery>& callbackQuery) override {}

    /// @brief Called when a new incoming shipping query is received.
    /// @note Only for invoices with flexible price
    void onShippingQuery(const Ptr<ShippingQuery>& shippingQuery) override {}

    /// @brief Called when a new incoming pre-checkout query is received. Contains full information about checkout
    void onPreCheckoutQuery(const Ptr<PreCheckoutQuery>& preCheckoutQuery) override {}

    /// @brief Called when a new poll state is received.
    /// @note Bots receive only updates about stopped polls and polls, which are sent by the bot
    void onPoll(const Ptr<Poll>& poll) override {}

    /// @brief Called when a user changed their answer in a non-anonymous poll.
    /// @note Bots receive new votes only in polls that were sent by the bot itself.
    void onPollAnswer(const Ptr<PollAnswer>& pollAnswer) override {}

    /// @brief Called when the bot's chat member status was updated in a chat.
    /// @note For private chats, this update is received only when the bot is blocked or unblocked by the user.
    void onMyChatMember(const Ptr<ChatMemberUpdated>& myChatMemberUpdated) override {}

    /// @brief Called when a chat member's status was updated in a chat.
    /// @note The bot must be an administrator in the chat and must explicitly specify “chat_member” in the list of allowed_updates to receive these updates.
    void onChatMember(const Ptr<ChatMemberUpdated>& chatMemberUpdated) override {}

    /// @brief Called when a request to join the chat has been sent.
    /// @note The bot must have the can_invite_users administrator right in the chat to receive these updates.
    void onChatJoinRequest(const Ptr<ChatJoinRequest>& chatJoinRequest) override {}

    /// @brief Called when a chat boost was added or changed.
    void onChatBoostUpdated(const Ptr<ChatBoostUpdated>& chatBoostUpdated) override {}

    /// @brief Called when a boost was removed from a chat.
    void onChatBoostRemoved(const Ptr<ChatBoostRemoved>& chatBoostRemoved) override {}

    /// @brief Called when the long polling getUpdates fails.
    void onLongPollError(const std::string& errorMessage, ErrorCode errorCode) override {}
};

int main() {
  MyBot bot;
  bot.start();
  return 0;
}

Usage (4 approaches)

1. FetchContent (recommended)

Simply use CMake's FetchContent in your project's CMakeLists.txt as below:

cmake_minimum_required(VERSION 3.10)
project(my_bot)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include(FetchContent)
FetchContent_Declare(tgbotxx
  GIT_REPOSITORY "https://github.com/baderouaich/tgbotxx"
  GIT_TAG main
)
FetchContent_MakeAvailable(tgbotxx)

add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} PUBLIC tgbotxx)

2. PkgConfig: clone and install the library locally, then use PkgConfig:

example
git clone https://github.com/baderouaich/tgbotxx
cd tgbotxx
cmake .. -DCMAKE_BUILD_TYPE=Release
sudo make install 
# On Windows run `make install` as administrator 
cmake_minimum_required(VERSION 3.10)
project(my_bot)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(PkgConfig REQUIRED)
pkg_check_modules(tgbotxx REQUIRED tgbotxx)

if (NOT tgbotxx_FOUND)
  message(FATAL_ERROR "Did you install tgbotxx locally?")
endif ()

add_executable(${PROJECT_NAME} main.cpp)
target_link_directories(${PROJECT_NAME} PUBLIC ${tgbotxx_LIBRARY_DIRS})
target_include_directories(${PROJECT_NAME} PUBLIC ${tgbotxx_INCLUDE_DIRS})
target_compile_options(${PROJECT_NAME} PUBLIC ${tgbotxx_CFLAGS_OTHER})
target_link_libraries(${PROJECT_NAME} PUBLIC ${tgbotxx_LIBRARIES})

3. find_package: clone and install the library locally, then use find_package(tgbotxx REQUIRED):

example
cmake_minimum_required(VERSION 3.10)
project(my_bot)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(tgbotxx REQUIRED)

if (NOT tgbotxx_FOUND)
  message(FATAL_ERROR "Did you install tgbotxx locally?")
endif ()

add_executable(${PROJECT_NAME} main.cpp)
target_link_directories(${PROJECT_NAME} PUBLIC ${tgbotxx_LIBRARY_DIRS})
target_include_directories(${PROJECT_NAME} PUBLIC ${tgbotxx_INCLUDE_DIRS})
target_compile_options(${PROJECT_NAME} PUBLIC ${tgbotxx_CFLAGS_OTHER})
target_link_libraries(${PROJECT_NAME} PUBLIC ${tgbotxx_LIBRARIES})

4. Submodule: Use tgbotxx as a project submodule (without installation)

example

You can also use this library as a submodule in your bot project without the need of installing it in your system. Use git clone or git submodule add the library:

git submodule add https://github.com/baderouaich/tgbotxx ./lib/tgbotxx

or

git clone https://github.com/baderouaich/tgbotxx ./lib/tgbotxx

Then add add_subdirectory(lib/tgbotxx) in your CMakeLists.txt.

cmake_minimum_required(VERSION 3.10)
project(my_bot)

add_subdirectory(lib/tgbotxx) # <-- clone tgbotxx in your project's lib/ directory

add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} PUBLIC tgbotxx) # <-- link with tgbotxx

Other actively maintained Telegram Bot C++ Libraries

  • tgbot-cpp: C++ library for Telegram bot API
  • tgbot: C++ library for Telegram Bot API with generated API types and methods

Refs:

Telegram Api Documentation