Giter VIP home page Giter VIP logo

aiotg's People

Contributors

akolechkin avatar alekseyl1992 avatar and3rson avatar bliz937 avatar creatorrr avatar derfenix avatar justdolanit avatar kozalosev avatar ldotlopez avatar marcoceppi avatar mfoxru avatar mon4ter avatar muhammedfurkan avatar muminoff avatar nonamenix avatar ogroleg avatar olehbozhok avatar pavkazzz avatar pooyamb avatar rahiel avatar rossnomann avatar shadrus avatar spirkaa avatar szastupov avatar un1t avatar verteen avatar vijfhoek avatar xalexo 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  avatar  avatar  avatar  avatar  avatar  avatar

aiotg's Issues

Add support for new_chat_members

The singular field has been deprecated for a long time (https://core.telegram.org/bots/api-changelog#may-18-2017) and has been removed from the documentation.
Please add support for the plural version.
Currently I do

@bot.handle('new_chat_member')
def example(chat, new_chat_member):
  new_chat_members = chat.message['new_chat_members']
  for new_chat_member in new_chat_members:
    foobar

but if telegram removes the field, all of us will no longer be able to receive these updates.
I think I can just make the decorator argument plural, but I am unsure.

I imagine this is just adding the plural version to the message types constant, but again I am unsure

Add conversation support

Hi, I was thinking about how it would be great to be able to use the power of async / await syntax to create connections of the type

async def conversation(chat: Chat):
    number = randint(1, 1000)
    await chat.send_text("Hello, give me a number")
    while True:
        response = await chat.response(r'^\d+$', unexpected='Sorry, I did not understand.')
        if response:
            response = int(response.group())
            if response > number:
                await chat.send_text('high')
            elif response < number:
                await chat.send_text('low')
            else:
                await chat.send_text('Correct!')
                break

aiohttp

Now i am going to work on webhook implementation for aiotg. Is it possible to change requirement aiohttp version to >= 1? There were some changes in http server implementation and i want to use its current api.

Add plugin system

We need a plugin system that allows to define new bot commands and handlers in separate modules. It would also be nice to be able enable/disable plugins without reloading the bot.

Issue with session

Hey @szastupov,

Was using until the new version bumped, never had an issue. After getting installed new version from pip, my code throws error. Guessing that it might have problem with aiohttp session.

My code:

# Asyncio
import asyncio

# UVLoop
import uvloop

# Asyncpg
from asyncpg import create_pool as create_pg_pool

# Aiobotocore
from aiobotocore import get_session as boto_session

# Bot
from bot import bot

# Misc
import os
from urllib.parse import urlparse

# Use uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())


async def run_bot():
    await bot.loop()


async def make_pg_pool():
    dsn = os.environ.get('DATABASE_URL')
    return await create_pg_pool(
        dsn=dsn,
        min_size=10,
        max_size=20)

async def make_s3_client(loop):
    aws_access_key_id = os.environ.get('AWS_ACCESS_KEY_ID')
    aws_secret_access_key = os.environ.get('AWS_SECRET_ACCESS_KEY')
    session = boto_session(loop=loop)
    return session.create_client(
        's3', region_name='us-east-1',
        aws_access_key_id=aws_access_key_id,
        aws_secret_access_key=aws_secret_access_key)

# Main event loop
loop = asyncio.get_event_loop()

# Attach postgres connection pool to bot
pg_pool = loop.run_until_complete(make_pg_pool())
setattr(bot, 'pg_pool', pg_pool)

# Attach s3 client to bot
s3_client = loop.run_until_complete(make_s3_client(loop))
setattr(bot, 's3_client', s3_client)


if __name__ == '__main__':
    import sys
    if len(sys.argv) == 2 and sys.argv[1] == 'loop':
        loop.run_until_complete(run_bot())
    else:
        bot.run_webhook(os.environ.get('APP_URL') + 'webhook')

Exception:

$ python main.py
Creating a client session outside of coroutine
client_session: <aiohttp.client.ClientSession object at 0x7f2fc36aa4e0>
DEBUG:botocore.loaders:Loading JSON file: /home/vb/.env/lib/python3.5/site-packages/botocore/data/endpoints.json
DEBUG:botocore.loaders:Loading JSON file: /home/vb/.env/lib/python3.5/site-packages/botocore/data/s3/2006-03-01/service-2.json
DEBUG:botocore.loaders:Loading JSON file: /home/vb/.env/lib/python3.5/site-packages/botocore/data/_retry.json
DEBUG:botocore.client:Registering retry handlers for service: s3
DEBUG:botocore.hooks:Event creating-client-class.s3: calling handler <function add_generate_presigned_post at 0x7f2fc3eac048>
DEBUG:botocore.hooks:Event creating-client-class.s3: calling handler <function add_generate_presigned_url at 0x7f2fc3ea6400>
DEBUG:botocore.args:The s3 config key is not a dictionary type, ignoring its value of: None
DEBUG:botocore.endpoint:Setting s3 timeout as (60, 60)
DEBUG:botocore.client:Defaulting to S3 virtual host style addressing with path style addressing fallback.
DEBUG:aiotg:api_call setWebhook, {'url': 'https://vb.muminoff.uz/webhook'}
Traceback (most recent call last):
  File "main.py", line 61, in <module>
    bot.run_webhook(os.environ.get('APP_URL') + 'webhook')
  File "/home/vb/project/aiotg/bot.py", line 118, in run_webhook
    loop.run_until_complete(self.set_webhook(webhook_url, **options))
  File "uvloop/loop.pyx", line 1203, in uvloop.loop.Loop.run_until_complete (uvloop/loop.c:25632)
  File "uvloop/future.pyx", line 146, in uvloop.loop.BaseFuture.result (uvloop/loop.c:109361)
  File "uvloop/future.pyx", line 101, in uvloop.loop.BaseFuture._result_impl (uvloop/loop.c:108900)
  File "uvloop/future.pyx", line 372, in uvloop.loop.BaseTask._fast_step (uvloop/loop.c:112669)
  File "/home/vb/project/aiotg/bot.py", line 248, in api_call
    response = await self.session.post(url, data=params)
  File "/home/vb/.env/lib/python3.5/site-packages/aiohttp/client.py", line 582, in __await__
    resp = yield from self._coro
  File "/home/vb/.env/lib/python3.5/site-packages/aiohttp/client.py", line 200, in _request
    with timer:
  File "/home/vb/.env/lib/python3.5/site-packages/aiohttp/helpers.py", line 750, in __enter__
    raise RuntimeError('Timeout context manager should be used '
RuntimeError: Timeout context manager should be used inside a task
ERROR:asyncio:Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7f2fc0514940>

Faced to this, this and this issues while searching with RuntimeError: Timeout context manager should be used inside a task.

Information:

$ python --version
Python 3.5.2

$ pip freeze
aiobotocore==0.2.1
aiohttp==1.3.3
aiotg==0.7.19
async-timeout==1.1.0
asyncpg==0.8.4
botocore==1.5.0
chardet==2.3.0
docutils==0.13.1
hashids==1.2.0
jmespath==0.9.1
multidict==2.1.4
pkg-resources==0.0.0
python-dateutil==2.6.0
six==1.10.0
uvloop==0.8.0
Wand==0.4.4
yarl==0.9.8

Any hints to fix or workaround?

AttributeError: module 'aiohttp' has no attribute 'post'

Version: aiotg==0.7.17

After I have run the following sample

from aiotg import Bot

bot = Bot(api_token="...")

@bot.command(r"/echo (.+)")
def echo(chat, match):
    return chat.reply(match.group(1))

bot.run()

I got the error:

  File "./venv/lib/python3.5/site-packages/aiotg/bot.py", line 82, in loop
    timeout=self.api_timeout
  File "./venv/lib/python3.5/site-packages/aiotg/bot.py", line 243, in api_call
    response = await aiohttp.post(url, data=params)
AttributeError: module 'aiohttp' has no attribute 'post'

Additional callback_query data in CallbackQuery __init__

Hello!

In my project I need to get information about who pressed button in chat, but as I was looking at source code, I found out, that __init__ method for aiotg.bot.CallbackQuery class is not saving some fields from callback_query key that is sent to webhook.

What is already gatherable:

  • message - may be gathered with Chat object
  • id - saved in self.query_id
  • data - saved in self.data

What is missing:

And there other fields from Telegram API docs, but not sure if usable:

  • inline_message_id - haven't worked with inline messages, so can't say anything about it
  • game_short_name - same here

I'm mostly interested in from field, but for a general purposes it would be better if all those fields will be available

Also maybe it would be better if fields are generated dynamicly from existing keys of callback_query, so it wouldn't be required to make new changes in future.

group_chat_created not in list of supported messages

In order to process an event when a bot joins a new group, group_chat_created needs to be in the list of supported events.

Example of payload:

{
  'update_id': XXXXXX,
  'message': {
    'message_id': 38,
    'from': {
      'id': XXXXXXX,
      'is_bot': False,
      'first_name': 'Marco',
      'last_name': 'Ceppi',
      'username': 'XXXXXXXX',
      'language_code': 'en-US'
    },
    'chat': {
      'id': -XXXXXXX,
      'title': 'Another Test',
      'type': 'group',
      'all_members_are_administrators': True
    },
    'date': 1518477717,
    'group_chat_created': True
  }
}

Old GET/POST API

After update to aiohttp 1.0.0, aiotg has deprecated syntax for GET and POST requests.
It should use aiohttp.ClientSession().

Handle text and commands at the same time

Hi! I think, this framework is great, and I use it sometimes.
Now I'm facing with next problem: I want my bot to have default text handler and also to have special handler for some commands
For example, I have next code:

image

Now, if I'm sending my bot command /start, but instead of handle_start_command callback, it will execute handle_text callback. What's the problem, and how to overcome it?

KeyError when processing the callback handler of an inline message

Working on my bot, I encountered a problem. To illustrate it, I've written a simple script shown below:

from aiotg import Bot, Chat, InlineQuery, CallbackQuery


bot = Bot(api_token="123456789:XXXXXXXXXXXXXXXXXXXXXXXXXX-YYYYYYYY", default_in_groups=True)

keyboard = {"inline_keyboard": [[{"callback_data": "clicked", "text": "Click me!"}]]}


@bot.command("/test")
def start(chat: Chat, match) -> None:
    chat.send_text("Hello!", reply_markup=bot.json_serialize(keyboard))


@bot.inline
def inline_query_handler(query: InlineQuery):
    query.answer([{
        "type": "article",
        "id": "0",
        "title": "Hello World",
        "description": "Testing...",
        "input_message_content": {"message_text": "Testing..."},
        "reply_markup": keyboard
    }])


@bot.callback
def callback_query_handler(chat: Chat, query: CallbackQuery) -> None:
    query.answer(text="Hello World")


if __name__ == '__main__':
    bot.run(debug=True)

By the way, I think it's kind of inconsistent behavior that the reply_markup parameter of the InlineQuery.answer() method strictly takes a dict, but the send_message() method requires explicit JSON serialization.

It does 3 things:

  1. responses to the /test command with a dummy message containing one inline button;
  2. supports the inline mode, suggesting another dummy message with one inline button to the user;
  3. handles button clicks identically, displaying a dummy text notification.

If we try to click on the button attached to the bot's message (either in the personal chat with bot itself or in a group chat), everything works fine. However, the click on the button of the user's message suggested by the bot, triggers a KeyError:

Traceback (most recent call last):
  File "test_aiotg.py", line 30, in <module>
    bot.run(debug=True)
  File "/home/kozalo/venv/lib/python3.7/site-packages/aiotg/bot.py", line 157, in run
    run_with_reloader(loop, bot_loop, self.stop)
  File "/usr/lib/python3.7/asyncio/base_events.py", line 568, in run_until_complete
    return future.result()
  File "/home/kozalo/venv/lib/python3.7/site-packages/aiotg/reloader.py", line 91, in run_with_reloader
    if isinstance(fut.result(), Event):
  File "/home/kozalo/venv/lib/python3.7/site-packages/aiotg/bot.py", line 131, in loop
    self._process_updates(updates)
  File "/home/kozalo/venv/lib/python3.7/site-packages/aiotg/bot.py", line 629, in _process_updates
    self._process_update(update)
  File "/home/kozalo/venv/lib/python3.7/site-packages/aiotg/bot.py", line 648, in _process_update
    coro = self._process_callback_query(update["callback_query"])
  File "/home/kozalo/venv/lib/python3.7/site-packages/aiotg/bot.py", line 613, in _process_callback_query
    chat = Chat.from_message(self, query["message"])
KeyError: 'message'

The description of the CallbackQuery type in the official documentation says:

If the button that originated the query was attached to a message sent by the bot, the field message will be present. If the button was attached to a message sent via the bot (in inline mode), the field inline_message_id will be present.

Therefore, callback queries issued by the messages sent by the user via inline mode don't have the message field, only an identificator of the inline message. Thus, it's not possible to instantiate a chat object from the missing message.

If it's OK to pass None instead of a Chat instance to the handler, then it's pretty easy to fix the issue:

def _process_callback_query(self, query):
    chat = Chat.from_message(self, query["message"]) if "message" in query else None
    cq = CallbackQuery(self, query)
    for patterns, handler in self._callbacks:
        match = re.search(patterns, cq.data, re.I)
        if match:
            return handler(chat, cq, match)

    # make an assumption that the inline mode is mostly used in group chats
    if chat and not chat.is_group() or self.default_in_groups:
        return self._default_callback(chat, cq)

Otherwise, I cannot suggest an acceptable solution. Sorry.

Bump new release

Hey, any way to bump a new release? My requirements.txt still includes -e git://github.com/szastupov/aiotg#egg=aiotg from master branch. Wanted to use pip version. Thanks.

Missing data in CallbackQuery

When you receive a CallbackQuery (when you press a button in an inline keyboard), you only get access to 'query_id' and 'data', but not to 'chat_instance', 'from' and 'message' data. This means that many users at many chats can be pressing these buttons and you don't know where it comes from.
Looking at class CallbackQuery.init all the information is in the src variable, which is not preserved after the init, so I propose that you add there something like self.chat_instance=src['chat_instance'], self.from_ = src['from'] and self.message=src['message'] (and possibly the complete self.src = src) to preserve all the information.

Option to send chat action automatically.

It would be nice to have something in _process_message to send the send_chat_action before sending a message. Like if it was chat.send_text() or chat.reply(), we can send the chat.send_chat_action('typing') for sure automatically if it's enabled in bot's settings. The same for audio and photos... The same approach already is done for tracking to botan, but we can send chat actions as well. Also, it would be nice to have it enabled by default.
Currently, almost 30% of the code for my bot are chat actions lol.

Argument "disable_notification" not working for send_photo method

Hi!
Thanks for this library, it's cool!

Not sure why, but "disable_notification" not working for send_photo,

with open('assets/some.jpg', 'rb') as f:
    await chat.send_photo(f, caption='example', disable_notification=True)

Here is trace:

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/lib/python3.5/asyncio/tasks.py", line 241, in _step
    result = coro.throw(exc)
  File "aiobot.py", line 62, in start
    await chat.send_photo(f, caption='example', disable_notification=True)
  File "/usr/lib/python3.5/asyncio/futures.py", line 361, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/usr/lib/python3.5/asyncio/tasks.py", line 296, in _wakeup
    future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
    raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/var/workspace/mybot/python3/lib/python3.5/site-packages/aiotg/bot.py", line 319, in _api_call
    response = await self.session.post(url, data=params)
  File "/var/workspace/mybot/python3/lib/python3.5/site-packages/aiohttp/helpers.py", line 102, in __await__
    ret = yield from self._coro
  File "/var/workspace/mybot/python3/lib/python3.5/site-packages/aiohttp/client.py", line 226, in _request
    session=self)
  File "/var/workspace/mybot/python3/lib/python3.5/site-packages/aiohttp/client_reqrep.py", line 104, in __init__
    self.update_body_from_data(data)
  File "/var/workspace/mybot/python3/lib/python3.5/site-packages/aiohttp/client_reqrep.py", line 264, in update_body_from_data
    body = FormData(body)()
  File "/var/workspace/mybot/python3/lib/python3.5/site-packages/aiohttp/formdata.py", line 141, in __call__
    return self._gen_form_data()
  File "/var/workspace/mybot/python3/lib/python3.5/site-packages/aiohttp/formdata.py", line 125, in _gen_form_data
    type(value), headers, value)) from exc
TypeError: Can not serialize value type: <class 'bool'>

Without this argument all works fine!

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.