Coder Social home page Coder Social logo

bottery's People

Contributors

alexandrebarbaruiva avatar bradshjg avatar delta9000 avatar elsaico avatar ewenchou avatar gabrielgradinaru avatar gabrielrf avatar humrochagf avatar jtemporal avatar kplaube avatar leportella avatar lucasrcezimbra avatar muriloviana avatar naveenbellary avatar nicoddemus avatar ozbek avatar pascalhein avatar phinfonet avatar rennerocha avatar rougeth avatar samukasmk avatar stummjr avatar supertassu avatar yusadolat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bottery's Issues

run bottery in production

I'd like to discuss how is the best way to deploy Bottery.

It is already possible to run bottery as a python command in uWsgi

$ uwsgi --http :8000 --py bot.py --master --processes 4 --threads 3 

or with gunicorn and aiohttp.worker.GunicornWebWorker

$ gunicorn bot:bot.server -b 127.0.0.1:8000 --worker-class aiohttp.worker.GunicornWebWorker

In booth cases, bot.run(server_port=7000) is called to start and configure Bottery.
Maybe we could extract part of runmethod for someting called start_app to avoid some unnecessary calls, as self.loop.run_forever() and server creation with asincio that is already handled by gunicorn.

bot.run() could call bot.start_app() and handle the additional steps to run the development server

I'd suggest an usage like:

#! /usr/bin/env python
from bottery import Bottery

SERVER_PORT = 7000

bot = Bottery(settings_module="mysettings")

@bot.patterns.regex('^.*$')
def parrot(message):
    return message

if __name__ == '__main__':
    bot.run(server_port=SERVER_PORT)
else:
    bot.start_app()

Comparison with other bot frameworks (errbot/Chatterbot)

errbot is another bot framework for Python.

It might nice for us to write a comparison between bottery and errbot, their philosophical differences, learn from their mistakes and incorporate some of their good ideas into bottery itself.

As mentioned, Chatterbot is another framework which we might write a comparison about.

Windows testing?

Are you guys interested in testing on Windows automatically as well?

I volunteer to open a PR with the proper configuration, someone owner of the repository just have to create an account/team on https://www.appveyor.com. ๐Ÿ˜

Support for context url groups

Bots become more awesome when they can react to some context, for example at a store support bot:

Store Bot
|-- Talk with sales
|    |-- Buy a product
|    |-- Contract a service
|    |-- Cancel a service
|-- Talk with tech support
|    |-- Problem with a product
|    |-- Problem with a service

Share bot functionality

I was thinking, some functionality like talking with Jenkins or GitHub could be shared with others so they can incorporate that functionality into their own bots, similar to how Hubot works. Is this something we would like to have for bottery?

Handle exception on view

In my instalation, if an exception occurs on a view the app hangs/ the loop dies.

I think it is just a matter of calling the view with a try: except: but would like to know if it is common to all and if anyone thank about a more elegant solution.

Obviously, the implemented view must handle the exception itself, but the core may have some client implementations error proof

Loop not being shutdown gracefully

Even running loop.stop() and then loop.close() we're getting those messages:

Task was destroyed but it is pending!
task: <Task pending coro=<TelegramEngine.polling() running at ../bottery/platform/telegram.py:102> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x10658e6a8>()]>>
Task was destroyed but it is pending!
task: <Task pending coro=<TelegramEngine.polling() running at ../bottery/platform/telegram.py:102> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x10658e4c8>()]>>

TelegramEngine reaches recursion limit after a while

With #79 solved, it seems a couple issues were unearthed.

After a while, since Python lacks tail-recursion due to a design decision by Guido himself, those consecutive calls to self.polling end up hitting the runtime's recursion depth limit, throwing a RecursionError in the process.

Of course, the bot becomes inoperant after this.

Allow more complex patterns (without context)

At Python Brasil, we talked a lot about how Pattern obj is so limited and how we could improve it. The main point of the discussion was how we could implement other "types" of patterns:

patterns = [
    # 1)
    Pattern('ping', ping),
    RegexPattern(r'^ping \d*$', regex_ping), # "ping 123" would be accepted
    StartswithPattern('/ping', regex_ping), # "/ping bottery" would be accepted

    # 2) or
    Pattern('ping', ping),
    Pattern(r'^ping$', regex_ping, type='regex'),
    Pattern('/ping', regex_ping, type='startswidth'),

    # 3) or
    Pattern('ping', ping),
    Pattern(r'^ping$', regex_ping, validator=regex_validator),
    Pattern('/ping', regex_ping, validator=startswith_validator),
    # where regex_validator and startswith_validator are the checkers
]

I believe the second "kind of" pattern is the easiest for who will use Bottery. But I think we should discuss it better.

@nicoddemus @muriloviana @mawkee @ElSaico @leportella

TelegramEngine.polling => Exception TimeoutError

Hi Folks,

With #91 solved, I updated my codebase. After a while app raise a exception, more details under here.

Task exception was never retrieved
future: <Task finished coro=<TelegramEngine.polling() done, defined at /usr/local/lib/python3.6/site-packages/bottery/platform/telegram.py:94> exception=TimeoutError()>
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/bottery/platform/telegram.py", line 102, in polling
    response = await self.api.get_updates(payload)
  File "/usr/local/lib/python3.6/site-packages/aiohttp/helpers.py", line 102, in __await__
    ret = yield from self._coro
  File "/usr/local/lib/python3.6/site-packages/aiohttp/client.py", line 241, in _request
    yield from resp.start(conn, read_until_eof)
  File "/usr/local/lib/python3.6/site-packages/aiohttp/client_reqrep.py", line 572, in start
    self._continue = None
  File "/usr/local/lib/python3.6/site-packages/aiohttp/helpers.py", line 743, in __exit__
    raise asyncio.TimeoutError from None
concurrent.futures._base.TimeoutError

This issue happened only once time, I'm cannot reproduce the error.

Thanks a lot ~

Key error at Telegram build_message

When we send something that isn't a message (e.g.: an edit to a sent message) to the bot, it breaks due to a the absence of the key 'message' at the response.

For example, when we edit a message, the response data contains 'edited_message' key instead 'message' which raises an key error at line 87 at telegram.py file:

 87, in build_message
    id=data['message']['message_id'],
KeyError: 'message'

Async handlers

Currently the handlers are not async functions. For simple interactions that is fine, but if the bot needs to do some I/O (accessing a database, consulting a website, etc) an async function would scale better.

License?

There is no license in the repository currently... if there's no license, a project is assumed to be closed source. I of course know that's not intentional. ๐Ÿ˜

If you don't know which license you want, please take a look at https://choosealicense.com/ ๐Ÿ‘

I usually use MIT for my projects.

[Telegram] KeyError: 'text' when bot was added in a group

When the bot was added in a group, it receives a message like Lucas Rangel Cezimbra invited bot but when bottery receives this message it comes without text, so raises an exception as below.

Traceback (most recent call last):
  File "/home/lucas/telegram-bot/.venv/lib/python3.6/site-packages/bottery/platform/telegram/engine.py", line 92, in polling
    await asyncio.gather(*tasks)
  File "/home/lucas/telegram-bot/.venv/lib/python3.6/site-packages/bottery/platform/telegram/engine.py", line 153, in message_handler
    message = self.build_message(data)
  File "/home/lucas/telegram-bot/.venv/lib/python3.6/site-packages/bottery/platform/telegram/engine.py", line 131, in build_message
    return Message(
KeyError: 'text

https://github.com/rougeth/bottery/blob/master/bottery/platform/telegram/engine.py#L133

Telegram documentation says that text is a optional field.

Is this a bug or am I doing something wrong?

If is a bug, how can we get around? We can use message_data.get('text') and set text to None when we do not have text? Or just return None instead of a message?

If it makes sense I can open a pull request.

Multiplatform

Would be great to run the same bot for telegram, messenger, slack, etc.

Consider adopting a code coverage service

Given the recent issues about code coverage, it might be nice to adopt one of the available code coverage services that have GitHub integration. The advantage is that those services keep a code coverage record of each branch and post code coverage information in each PR. The two I know about are:

Make sure to browse the links of the examples above to get an idea of what is provided by those services.

Decorating views

How about we use decorators instead of having an explicit registry?

# quick example of a ping pong bot
from bottery.conf.patterns import DefaultPattern, Pattern

@Pattern('ping')
def pong(message):
    return "pong!"

@DefaultPattern
def not_found(message):
    return "Sorry, I didn't understand you :/"

Create better exceptions

Stop using directly Exception class:

bottery/app.py
39:            raise Exception('No platform configured')

bottery/conf/settings.py
17:            raise Exception('Could not find settings module')

bottery/platform/__init__.py
15:        raise Exception('Could not find patterns module')
25:    # raise Exception('No Pattern found!')

tests/test_app.py
34:    with pytest.raises(Exception):

tests/test_settings.py
39:    with pytest.raises(Exception):

Allow more complex conversations (context)

As we talked last time, I think it would be nice for bottery to support more complex conversations by allowing multiple replies from within a message handler.

async def purchase(message, head_set):
    categories = get_product_categories()
    resp = await head_set.talk(f'Thanks for shopping! Here are our product categories: {categories}')
    while resp not in categories:
        resp = await head_set.talk(f'Sorry, I do not recognize this category. Please select from: {categories}')
        if resp == 'I want to bail out':
            return f'OK, sorry to see you go!'

    ...


patterns = [
    Pattern('I want to buy stuff', purchase),
    Pattern('Give me goods!', purchase),
]

(head_set is a little joke of course ๐ŸŽง)

The main advantage of this approach is that we keep the context of the conversation inside the same function. Without this the user will have to maintain that context themselves, which is hard to do and doesn't scale very well. Pairing that with some natural language processing (#4) would make bottery well suited for complex interactions.

Problems with python throws

Whats happen?

For any reason python does not throw any exception during bottery run

How reproduce it?

In my case I'm testing some stuff that I've done in this PR: #78, so you can jump on my branch and do this steps:

  • Guarantee that bottery are local pip install -e ../bottery/path
  • Jump to my PR (or go to any function and force a error)
  • You will se that bottery still running without alerts or logs

Concentrate all dependencies at setup.py

We have some dependencies at tox.ini that are not at setup.py and others duplicated on both files. We should keep them at setup.py on extras_require except codecov, that should stay only on tox.ini.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.