Skip to content

Instantly share code, notes, and snippets.

@teito-dev
Last active February 26, 2022 02:04
Show Gist options
  • Save teito-dev/7c8e8bcb4dfd6a191ccee9040f1a0ccf to your computer and use it in GitHub Desktop.
Save teito-dev/7c8e8bcb4dfd6a191ccee9040f1a0ccf to your computer and use it in GitHub Desktop.
Frank Documentation for pyTelegramBotAPI

pyTelegramBotAPI

starter code

import telebot

# I just import the part down below seperately just for convinience
from telebot import types 

# Initialising the bot instance
bot = telebot.TeleBot("TOKEN HERE")
admin_id = 572771786 # This is just my chat_id

@bot.message_handler(content_types=['text'])
def reply_text(message):
    if message.chat.type == "private":
        try:
            bot.send_message(message.from_user.id,
                             "Me no dm , bb")
        except Exception as e:
            print(e)
            pass

try:
    bot.send_message(admin_id, 'I am BAC')
    bot.polling()
except Exception as e:
    bot.send_message(admin_id, "I am feeling ded oni-chan due to %s" % (e))
    print(e)

Examples of Implementation of various features

sending various content type messages

The ones feature here are text , images , videos , documents

but there are also bot.send_invoice() bot.send_game() bot.send_location() bot.send_media_group() bot.send_sticker() bot.send_voice() bot.send_video_note() # Similar to send_video , just more options available bot.send_sticker() you can check their docstrings out or read their source code , i might add examples for these later , but its very easy to figure those out , all of them have docstrings provided , and its there in the main readme file of the repo

# For Text

# For personal message
bot.send_message(message.from_user.id,"DMed You")
# For message directly on the chat wherever the request was made
bot.send_message(message.chat.id,"MaYbE I DmEd You")

For photo

photo = open('/tmp/photo.png', 'rb')
bot.send_photo(message.from_user.id, photo)
bot.send_photo(message.from_user.id, "file-id here , if already has been sent to bot in telegram-server , you dont need to redownload and upload it ")

'''
You can get the file-id from 
message.document.file_id
'''

For Document

document_data = open("docu.txt",rb)

bot.send_document(message.from_user.id, document_data)

For video

video_name = "Rose are Red"
video_id = "vab"

edit_buttons = types.InlineKeyboardMarkup()
edit_buttons.add(types.InlineKeyboardButton("Cancel Video", callback_data=f"makechange-cancel_video-{video_name}-{video_id}"))

caption_text = "Roses are red \n Violets are Blue \n Youre not reading this gist \n Im reading YOU"

video = open(video_path, 'rb')
bot.send_video(message.from_user.id, video,reply_markup=edit_buttons, caption=caption_text)

'''
I added in some reply markup here too , Heres how to fetch it back and also why i made it that way
'''

Callback Function

Now lets combine the video example with some callback to show you what i mean

'''
Lets put that previous example of send_video behind a message_handler which sends that video
when user sends /start or sends a text where using regex we can find the term oki
'''

@bot.message_handler(regexp='oki')
@bot.message_handler(commands=['start'])
def send_welcome(message):
    # I will explain what this line below does later 
    bot.clear_step_handler_by_chat_id(message.from_user.id)
    # Now
    video_name = "Rose are Red"
    video_id = "vab"
    video_path = "umaruchan_trailer.mp4"
    edit_buttons = types.InlineKeyboardMarkup()
    edit_buttons.add(types.InlineKeyboardButton("Cancel Video", callback_data=f"makechange-cancel_video-{video_name}-{video_id}"))
    caption_text = "Roses are red \n Violets are Blue \n Youre not reading this gist \n Im reading YOU"
    video = open(video_path, 'rb')
    bot.send_video(message.from_user.id, video,reply_markup=edit_buttons, caption=caption_text)

@bot.callback_query_handler(func=lambda call: True)
def callback_handler(message):
    # Will explain this later
    bot.clear_step_handler_by_chat_id(message.from_user.id)
    
    if str(message.data).startswith("makechange"):
        
        '''
        Splitting the callback string 
        f"makechange-cancel_video-{video_name}-{video_id}"))
        '''
        
        details = str(message.data).split("-")
        
        operation_type = details[1] # aka fetching cancel_video 
        video_name = details[2]
        video_id = details[3]

        # Now you can take this info and implement that operation , dats on YOU

Checking message content type

Depending on your project you either need to check the content type from the message object itself or the just flag it with the message handler to parse those contents , but the underlying implementation is same for both of them

From the message object directly

# this variable store the content type 

message.content_type 

# These are the possibilities 
'''
text, audio, document, photo, sticker, video, video_note, voice, location, contact, new_chat_members, left_chat_member, new_chat_title, new_chat_photo, delete_chat_photo, group_chat_created, supergroup_chat_created, channel_chat_created, migrate_to_chat_id, migrate_from_chat_id, pinned_message
'''

# You can check for them using 

if message.content_type == "text":
    pass
elif message.content_type == "audio":
    pass

Making a seperate message handler for a particular content type

@bot.message_handler(content_types=['document', 'audio'])
def handle_docs_audio(message):
	bot.send_message(message.from_user.id,f"I am of type - {message.content_type}")

Now here's the feature I love the most in pyTelegramBotAPI

Step Handlers

It streamlines my workflow a ton , without me having to worry about detecting at what step into the telegram bot the person is in and decide on the reply i should send to them It also helps me save the steps and make it persistent so that even in case the bot restarts It knows exactly what step the user was , and the bot doesnt have to restart

Lets say youre at a particular message handler which sets people in into a book buying workflow when you press /book This can be implemented by the following code

import telebot

# I just import the part down below seperately just for convinience
from telebot import types 

# Initialising the bot instance
bot = telebot.TeleBot("TOKEN HERE")
admin_id = 572771786 # This is just my chat_id

@bot.message_handler(commands=['book'])
def book_time(message):
    bot.send_message(message.from_user.id,"Enter the book name")
    bot.register_next_step_handler(message.from_user.id, reply_parser,"Random Argument1","Random Arg 2")

'''
The function name doesnt have to be reply_parser you can use any function name just use the same one
in the bot.register_next_step_handler() function 
'''
def reply_parser(message,*args):
    # Clears the step handler , now that you have reached this step
    bot.clear_step_handler_by_chat_id(message.from_user.id)

    if message.content_type == "text":
        book_name = message.text
        random_arg_1 = args[0] 
        '''
        Instead of random args you could have sent a string to find what step
        the user was in and then use if else to run that step
        '''
        random_arg_2 = args[1]
        bot.reply_to(message, f"Book found:{book_name} and also {random_arg_1},{random_arg_2}")


try:
    # This enables saving of the step handler data , so that even if you restart the bot
    # The user data remains persistent 
    bot.enable_save_next_step_handlers(delay=2, filename="./.handler-saves/step.save")
    bot.load_next_step_handlers()

    bot.send_message(admin_id, 'I am BAC')
    bot.polling()
except Exception as e:
    bot.send_message(admin_id, "I am feeling ded oni-chan due to %s" % (e))
    print(e)

Have a great day !

@teito-dev
Copy link
Author

Roses are red
Violets are Blue
If you dont like it
Your pp is blue

XDDDDDDDD
Just kidding

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment