Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

command handler pull requests #47 and #51 #52

Closed
njittam opened this issue Sep 2, 2015 · 5 comments
Closed

command handler pull requests #47 and #51 #52

njittam opened this issue Sep 2, 2015 · 5 comments
Assignees

Comments

@njittam
Copy link
Contributor

njittam commented Sep 2, 2015

I noticed that there are two command handlers now. The EnhancedBot from mASOUDd in #47 and command_handler.py from me in #51.

I want to discuss what you guys think of the two. And maybe look at some way to combine them so that there is only one command handler in the package.

some of the main differences are:

The way to create the command handler.
EnhancedBot:

you just create a bot and all the tools are in it.

command_handler:

you create a new class with inherits CommandHandler or CommandHandlerWithHelp.
CommandHandler has a self.bot attribute.

The way to create a command.
EnhancedBot:

To create a command you simply do this.

bot = EnhancedBot(token=token)
@bot.command('/bla')
def some_name(command,user_id):
    return ("bla"), None, None)

(I personally love this system as well but I didn't know how to make it.)

command_handler:

create a new method in your class. which starts with 'command_' and takes update.

class myHandler(CommandHandlerWithHelp):
    def command_bla(self, update):
        chat_id = update.message.chat.id
        self.bot.sendMessage(chat_id, 'bla') 
The way to start the command handler.

but I think this is less important because they do basically the same thing here.

EnhancedBot:
while True:
     bot.processUpdates()
     time.sleep(3)
command_handler:
bot = telegram.Bot(token=token)
my_command_handler = myHandler(bot)
my_command_handler.run()  # every command is a new thread.

My opinion.

to it as usable as possible to me it has the following requirements:
I implemented some of these in my command_handler

  • have an easy way to write a method and have that automatically detected as a command and that particular method is run when the command is sent to the bot.
  • As a response be able to make use of the whole telegram api. Now and in the future. (E.G. send a video as response)
  • blocking statements should be handled by the command handler.
  • If I run a bot it should run until I and only I stop it. and not when a error is raised in a command.
  • I want to be able to send arguments with my command
@leandrotoledo
Copy link
Member

First of all, thank you for your awesome contribution here. Nice work!
The pull request you saw is not 100% functional, it was just an idea, and I think you already got the best of it. Indeed I do agree we could merge some functionalities.

have an easy way to write a method and have that automatically detected as a command and that particular method is run when the command is sent to the bot.

Agree, if we are combining decorators we could do something like this:
@bot.command
def hello(bot, message, args):
bot.sendMessage(message.chat_id, 'Hello World!')
or even
@bot.command
def hello(chat, message, args):
print message.text
chat.sendMessage('Hello World!) # chat object inherits bot object and self parse chat_id as arg

As a response be able to make use of the whole telegram api. Now and in the future. (E.G. send a video as response)

Not sure what you mean by that, but command_handler will be an additional layer to core library, devs can go either way by doing manual long polling or using command handler.

blocking statements should be handled by the command handler.

Agree, with a decorator to identify command functions.

If I run a bot it should run until I and only I stop it. and not when a error is raised in a command.

Partially agree, there should be an option for that. Imagine someone trying to run a bot with an invalid token not catching errors (remember logging is not a good thing to auto enable for libraries).

I want to be able to send arguments with my command

Sure.

def hello(chat, message, args):

One more thing. I've been thinking about in event driven architecture, telegram offers some events where we could turn into useful decorators, how so:

on.new_chat_participant
on.left_chat_participant
on.new_chat_title
on.new_chat_photo
on.delete_chat_photo
etc etc

I'm back home this long weekend so I'll be able to help, please feel free to ping me on telegram (@leandrotoledo).

Once again, thanks for your work here.

@njittam
Copy link
Contributor Author

njittam commented Sep 6, 2015

First of all thank you! you are the one doing all the great work here.
Secondly, I am building my own bot and I have a weird bug where it just stops to receive messages after some time. I haven't had time to fully debug this. So I want to get this bug out first.

As a response be able to make use of the whole telegram api. Now and in the future. (E.G. send a video as response)

Not sure what you mean by that, but command_handler will be an additional layer to core library, devs can go either way by doing manual long polling or using command handler.

As I said I'm building a bot for myself and it needs to be able to respond with a location. #47 is not able to do this now.
Also, perhaps telegram will add a feature sendSmell in the future. and I want to make use of it without changing the command handler. #47 is also not able to do this now.
however these things are easy to change.

If I run a bot it should run until I and only I stop it. and not when a error is raised in a command.

Partially agree, there should be an option for that. Imagine someone trying to run a bot with an invalid token not catching errors (remember logging is not a good thing to auto enable for libraries).

Indeed it is true that a program should always stay debugable.

I want to be able to send arguments with my command

Sure.

def hello(chat, message, args):

Well this not exactly what I meant. I meant that I want the users of the bot to be able to sent arguments alongside a comment. But I do think an update or just a message object will be enough information to handle a command. But only text a user send won't be sufficient.

One more thing. I've been thinking about in event driven architecture, telegram offers some events where we could turn into useful decorators.

I think this is a really nice idea. Maybe you can even replace the getUpdates with some events. for example:
on.message_sent

I was also thinking of implementing a nice way to create to create a command with multiple messages. An Example of what I mean by that is for example the /setuserpic from BotFather.
first you send one message with /setuserpic then the bot sends you a message and the you send a second message with the picture.
This is the way telegram makes their own bots.

  1. user sends a message that starts with '/'.
  2. to bot sends a reply (optionally with information what it wants to receive).
  3. (optionally)
    a. the user sends the message according to that information.
    b. the user sends the message not according to that information.

a. if 3.a and no more messages are needed by the command then send exit message
b. if 3.a and some messages are still needed by the command then 2.
c. if 3.b send error message and 3.

I don't know how to do this and I haven't done much thinking about this problem but I want to share it because maybe someone already has some neat idea about this.
How I do this kind of things now is to make long command_ methods with and long indentations.

@naveenvhegde
Copy link

Many thanks for the contribution.

I second @leandrotoledo idea on event driven architecture. data should be emitted by event handler, getUpdates, increment lastupdatedid and polling mechanism should be completely abstracted out from user.

an ideal event driven command handler should be completely handled by "Observer" design patterns. Library requests for listeners (callbacks) for a given action

def start_command_handler_function(bot, update):
     #handle how start command should behave

def reset_command_handler_function(bot, update):
    #handle how reset command should behave

def message_handler_function
    # handle all the other messages, which are not command

def main():
     bot = Bot("TOKEN")
     bot.onCommand("start", start_command_handler_function)
     bot.onCommand("reset", reset_command_handler_function)
     bot.onMessage(message_handler_function)
     bot.start(timeout=2)

if __name__ == "__main__":
    main();

sample example (Implemented in c++)
https://github.com/reo7sp/tgbot-cpp/blob/master/include/tgbot/EventBroadcaster.h
https://github.com/reo7sp/tgbot-cpp/blob/master/include/tgbot/EventHandler.h

Thanks,
Naveen

@rbpasker
Copy link
Contributor

rbpasker commented Dec 2, 2015

Regarding the EnhancedBot, it's a nice idea, but it not only doesn't work with the Updater, it conflicts with the Dispatcher notion in Updater.

It would be better to extend Dispatcher in master to add, for example, a method processUpdates() that works synchronously like the one in EnhancedBot.

Then we could add method decorators for the various types of handlers.

Synchronous bots can then use Dispatcher directly, and threaded bots can use Updater.

@leandrotoledo
Copy link
Member

@jh0ker has implemented a really nice code for this feature request, many ideas match the discussion we had here, so I'll mark this one as obsolete. Please feel free to reopen in case I'm missing something.

Lastest version should be available by
$ pip install python-telegram-bot --upgrade

Also, some good kick off can be found here
https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/echobot2.py

@github-actions github-actions bot locked and limited conversation to collaborators Aug 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants