Pretending that telegram bot is typing? - bots

How can I make a bot to pretend that it is typing a message?
The following text appears in the chat when the bot pretend to type:
I use the python aiogram framework but a suggestion for the native Telegram API would be also helpful.

I seriously suggest using the python-telegram-bot library which has an extensive Wiki. The solution for what you want is described in code snippets.
You can manually send the action:
bot.send_chat_action(chat_id=chat_id, action=telegram.ChatAction.TYPING)
Or create a decorator which can then be used on any function you wish to show that action on whilst processing:
from functools import wraps
from telegram import (ChatAction)
def send_typing_action(func):
"""Sends typing action while processing func command."""
#wraps(func)
def command_func(update, context, *args, **kwargs):
context.bot.send_chat_action(chat_id=update.effective_message.chat_id, action=ChatAction.TYPING)
return func(update, context, *args, **kwargs)
return command_func
#send_typing_action
def my_handler(update, context):
pass # Will send 'typing' action while processing the request.

For aiogram module you can use types.Message built in method answer_chat_action.
from aiogram import types
async def answer(message: types.Message):
await message.answer_chat_action("typing")
await message.answer("Hi!")
Here is another action types such as upload_photo, record_video_note and so on. And here is aiogram documentation.

Related

What is the preferred way to call synchronous code from async routes in Sanic?

I'm researching Sanic as we're looking for alternatives to our flask-based rest services. I'm intriguied by the async nature of sanic, but I know that we'll bump into a lot of code that simply won't support async (we use a ton of boto3 and also some ORMs on top of DynamoDB for example, none of which support awaiting).
So: I need to find the cleanest way of being able to run synchronous code inside an async framework like Sanic. In python 3.7 there's the asyncio.create_task call which I'm finding interesting.
Wondering if this would be a possible way to go:
main.py:
#default boilerplate sanic code excluded for brevity
from app_logic import AppLogic
#app.route("/")
async def test(request):
task = await asyncio.create_task(AppLogic.sync_request('https://stuff.com'))
return json({"hello": "world", 'status_code': task.status_code})
app_logic.py:
import requests
class AppLogic(object):
#staticmethod
async def sync_request(url='https://myurl.com'):
#Some non-async library/code thingy
print('requesting the thing')
return requests.get(url)
This seems to work, and the the returned task object is a regular requests response.
However, I have no idea if this is "safe" - eg I'm not sure how I can investigate the event loop and verify that it's not blocking in any way. I'm sure there's also other reasons for this approach being completely dumb, so lay them on me :-)

Django viewflow: not receiving flow_finished signal

I'm trying to catch the flow_finished signal from django viewflow like this
flow_finished.connect(function)
but it's not working. The function isn't called even if the flow finishes.
Any help please, I'm pretty lost.
In my app's init.py I added this
from django.apps import AppConfig
default_app_config = 'test.TestConfig'
class TestConfig(AppConfig):
name = 'test'
verbose_name = 'Test'
def ready(self):
import viewflow.signals
First, you need to ensure that you properly configured you app config, and the ready method really been called. Check your installed apps that you properly included your TestConfig, or if you use shortcuts, check you test/__init__.py default_app_config value
from viewflow.signals import flow_finished
def receiver(sender, **kwargs):
print('hi')
class TestConfig(AppConfig):
name = 'test'
def ready(self):
flow_finished.connect(receiver)
But generally, using signals to weave your codebase is a bad taste. To call an action before flow.End you can explicitly add flow.Handler. That's the recommended solution.

python tornado how to get id of a edge

I have a web application that runs on flask web framework. Flask couldn't answer application requirements anymore. So we have decided to migrate tornado.
I need to handle below two request.
/entry GET Method
/entry/id GET Method
When first request called it must return authenticated entry.
When second request called it must return the entry whose entry_id
is id
Is there a different nice solution to handle above request except my solution. The solution i have found it creates cyclomatic complexity.
def get(self):
id = self.request.path.split('/')[-1]
if id is None:
#return authenticated user
else:
#return the user whose entry_id is id
Note: I am looking a solution like this:
#rest_user.route('/user', methods=['GET'])
#some code
#rest_user.route('/user/<user_id>', methods=['GET'])
#some code
The analogous arrangement in Tornado uses two handler classes (perhaps with a common base class for shared methods):
class AuthedUserHandler(RequestHandler):
def get(self):
...
class UserHandler(RequestHandler):
def get(self, user_id):
...
app = Application([
('/user', AuthedUserHandler),
('/user/(.*)', UserHandler),
])

PyQt auto slots: not called when decorated with a wrapper

I have a QWidget created via Qt Designer that has a QPushButton named foo, and the QWidget has a method named on_foo_clicked:
class MyWidget(QWidget):
def __init__(self):
...
#pyqtSlot()
def on_foo_clicked(self):
pass
Firstly, the on_foo_clicked is only called if it is decorated with pyqtSlot(). If I remove that decorator, I have to manually connect the self.ui.foo (of type QPushButton) to self.on_foo_clicked in MyWidget's initializer, yet I could not find any documentation about this.
Secondly, if I want to use my own decorator like this:
def auto_slot(func):
#pyqtSlot()
def wrapper(self):
func(self)
return wrapper
...
#auto_slot
def on_foo_clicked(self):
pass
it no longer works. But the following works:
def auto_slot(func):
return pyqtSlot()(func)
So the issue is not the replacement of pyqtSlot by another decorator, but rather that for some reason the wrapper function causes the auto connection mechanism to fail. Note that the above issue only affects automatic connections; if I add a line in MyWidget.__init__ to explicitely connect the self.ui.foo button to self.on_foo_clicked, then the auto_slot decorator with wrapper works as expected and the method gets called when click button.
Any ideas if there is something I can do to auto_slot with wrapper so that it will work even with automatically connected slots?
The reason I want this is so that the wrapper can trap exception raised by slot (indication of a bug) and print to console.
Just occurred to me that the problem is that wrapper function does not have the right name to be found by the auto connection system. So the following fixes the problem:
from functools import wraps
def auto_slot(func):
#wraps(func)
def wrapper(self):
func(self)
return pyqtSlot()(wrapper)

Can I use 2 receiver decorators on a django signal?

Is it possible to make this signal also trigger on superuser creation using a decorator?
#receiver(post_save, sender=User)
def checkin_added(sender, instance, created, **kwargs):
if created:
Settings.objects.create(user=instance)

Resources