Extended Telegram integration
This commit is contained in:
parent
fd5abc748f
commit
de429a5b7d
5 changed files with 130 additions and 32 deletions
|
@ -1,8 +1,11 @@
|
||||||
from typing import List, Optional
|
import re
|
||||||
|
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
from platypush.backend import Backend
|
from platypush.backend import Backend
|
||||||
from platypush.context import get_plugin
|
from platypush.context import get_plugin
|
||||||
from platypush.message.event.chat.telegram import MessageEvent, CommandMessageEvent
|
from platypush.message.event.chat.telegram import MessageEvent, CommandMessageEvent, TextMessageEvent, \
|
||||||
|
PhotoMessageEvent, VideoMessageEvent, ContactMessageEvent, DocumentMessageEvent
|
||||||
from platypush.plugins.chat.telegram import ChatTelegramPlugin
|
from platypush.plugins.chat.telegram import ChatTelegramPlugin
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,7 +15,11 @@ class ChatTelegramBackend(Backend):
|
||||||
|
|
||||||
Triggers:
|
Triggers:
|
||||||
|
|
||||||
* :class:`platypush.message.event.chat.telegram.MessageEvent` when a message is received.
|
* :class:`platypush.message.event.chat.telegram.TextMessageEvent` when a text message is received.
|
||||||
|
* :class:`platypush.message.event.chat.telegram.PhotoMessageEvent` when a photo is received.
|
||||||
|
* :class:`platypush.message.event.chat.telegram.VideoMessageEvent` when a video is received.
|
||||||
|
* :class:`platypush.message.event.chat.telegram.ContactMessageEvent` when a contact is received.
|
||||||
|
* :class:`platypush.message.event.chat.telegram.DocumentMessageEvent` when a document is received.
|
||||||
* :class:`platypush.message.event.chat.telegram.CommandMessageEvent` when a command message is received.
|
* :class:`platypush.message.event.chat.telegram.CommandMessageEvent` when a command message is received.
|
||||||
|
|
||||||
Requires:
|
Requires:
|
||||||
|
@ -21,46 +28,48 @@ class ChatTelegramBackend(Backend):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, commands: Optional[List[str]] = None, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
"""
|
|
||||||
:param commands: Optional list of commands to be registered on the bot (e.g. 'start', 'stop', 'help' etc.).
|
|
||||||
When you send e.g. '/start' to the bot conversation then a
|
|
||||||
:class:`platypush.message.event.chat.telegram.NewCommandMessageEvent` will be triggered instead of a
|
|
||||||
:class:`platypush.message.event.chat.telegram.NewMessageEvent` event.
|
|
||||||
"""
|
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.commands = commands or []
|
|
||||||
self._plugin: ChatTelegramPlugin = get_plugin('chat.telegram')
|
self._plugin: ChatTelegramPlugin = get_plugin('chat.telegram')
|
||||||
|
|
||||||
def _msg_hook(self):
|
def _msg_hook(self, cls: Type[MessageEvent]):
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
def hook(update, context):
|
def hook(update, context):
|
||||||
self.bus.post(MessageEvent(chat_id=update.effective_chat.id,
|
self.bus.post(cls(chat_id=update.effective_chat.id,
|
||||||
message=self._plugin.parse_msg(update.effective_message).output,
|
message=self._plugin.parse_msg(update.effective_message).output,
|
||||||
user=self._plugin.parse_user(update.effective_user).output))
|
user=self._plugin.parse_user(update.effective_user).output))
|
||||||
|
|
||||||
return hook
|
return hook
|
||||||
|
|
||||||
def _command_hook(self, cmd):
|
def _command_hook(self):
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
def hook(update, context):
|
def hook(update, context):
|
||||||
self.bus.post(CommandMessageEvent(command=cmd,
|
msg = update.effective_message
|
||||||
chat_id=update.effective_chat.id,
|
m = re.match('\s*/([0-9a-zA-Z]+)\s*(.*)', msg.text)
|
||||||
message=self._plugin.parse_msg(update.effective_message).output,
|
cmd = m.group(1).lower()
|
||||||
|
args = [arg for arg in re.split('\s+', m.group(2)) if len(arg)]
|
||||||
|
self.bus.post(CommandMessageEvent(chat_id=update.effective_chat.id,
|
||||||
|
command=cmd,
|
||||||
|
cmdargs=args,
|
||||||
|
message=self._plugin.parse_msg(msg).output,
|
||||||
user=self._plugin.parse_user(update.effective_user).output))
|
user=self._plugin.parse_user(update.effective_user).output))
|
||||||
|
|
||||||
return hook
|
return hook
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# noinspection PyPackageRequirements
|
# noinspection PyPackageRequirements
|
||||||
from telegram.ext import CommandHandler, MessageHandler, Filters
|
from telegram.ext import MessageHandler, Filters
|
||||||
|
|
||||||
super().run()
|
super().run()
|
||||||
telegram = self._plugin.get_telegram()
|
telegram = self._plugin.get_telegram()
|
||||||
dispatcher = telegram.dispatcher
|
dispatcher = telegram.dispatcher
|
||||||
dispatcher.add_handler(MessageHandler(Filters.all, self._msg_hook()))
|
|
||||||
|
|
||||||
for cmd in self.commands:
|
dispatcher.add_handler(MessageHandler(Filters.text, self._msg_hook(TextMessageEvent)))
|
||||||
dispatcher.add_handler(CommandHandler(cmd, self._command_hook(cmd)))
|
dispatcher.add_handler(MessageHandler(Filters.photo, self._msg_hook(PhotoMessageEvent)))
|
||||||
|
dispatcher.add_handler(MessageHandler(Filters.video, self._msg_hook(VideoMessageEvent)))
|
||||||
|
dispatcher.add_handler(MessageHandler(Filters.location, self._msg_hook(ContactMessageEvent)))
|
||||||
|
dispatcher.add_handler(MessageHandler(Filters.document, self._msg_hook(DocumentMessageEvent)))
|
||||||
|
dispatcher.add_handler(MessageHandler(Filters.command, self._command_hook()))
|
||||||
|
|
||||||
self.logger.info('Initialized Telegram backend')
|
self.logger.info('Initialized Telegram backend')
|
||||||
telegram.start_polling()
|
telegram.start_polling()
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
from platypush.message.event import Event
|
from platypush.message.event import Event
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,8 +20,32 @@ class CommandMessageEvent(MessageEvent):
|
||||||
"""
|
"""
|
||||||
Event triggered when a new message is received by the Telegram bot.
|
Event triggered when a new message is received by the Telegram bot.
|
||||||
"""
|
"""
|
||||||
def __init__(self, command: str, *args, **kwargs):
|
def __init__(self, command: str, cmdargs: Optional[List[str]] = None, *args, **kwargs):
|
||||||
super().__init__(*args, command=command, **kwargs)
|
super().__init__(*args, command=command, cmdargs=(cmdargs or []), **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class TextMessageEvent(MessageEvent):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PhotoMessageEvent(MessageEvent):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class VideoMessageEvent(MessageEvent):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ContactMessageEvent(MessageEvent):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class LocationMessageEvent(MessageEvent):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DocumentMessageEvent(MessageEvent):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# vim:sw=4:ts=4:et:
|
# vim:sw=4:ts=4:et:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional, List
|
||||||
|
|
||||||
from platypush.message.response import Response
|
from platypush.message.response import Response
|
||||||
|
|
||||||
|
@ -161,4 +161,12 @@ class TelegramUserResponse(Response):
|
||||||
}, **kwargs)
|
}, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class TelegramUsersResponse(Response):
|
||||||
|
# noinspection PyShadowingBuiltins
|
||||||
|
def __init__(self,
|
||||||
|
users: List[TelegramUserResponse],
|
||||||
|
*args, **kwargs):
|
||||||
|
super().__init__(*args, output=[user.output for user in users], **kwargs)
|
||||||
|
|
||||||
|
|
||||||
# vim:sw=4:ts=4:et:
|
# vim:sw=4:ts=4:et:
|
||||||
|
|
|
@ -12,7 +12,7 @@ from telegram.message import Message as TelegramMessage
|
||||||
from telegram.user import User as TelegramUser
|
from telegram.user import User as TelegramUser
|
||||||
|
|
||||||
from platypush.message.response.chat.telegram import TelegramMessageResponse, TelegramFileResponse, \
|
from platypush.message.response.chat.telegram import TelegramMessageResponse, TelegramFileResponse, \
|
||||||
TelegramChatResponse, TelegramUserResponse
|
TelegramChatResponse, TelegramUserResponse, TelegramUsersResponse
|
||||||
from platypush.plugins import Plugin, action
|
from platypush.plugins import Plugin, action
|
||||||
|
|
||||||
|
|
||||||
|
@ -667,6 +667,60 @@ class ChatTelegramPlugin(Plugin):
|
||||||
first_name=chat.first_name,
|
first_name=chat.first_name,
|
||||||
last_name=chat.last_name)
|
last_name=chat.last_name)
|
||||||
|
|
||||||
|
@action
|
||||||
|
def get_chat_user(self, chat_id: Union[int, str], user_id: int, timeout: int = 20) -> TelegramUserResponse:
|
||||||
|
"""
|
||||||
|
Get the info about a user connected to a chat.
|
||||||
|
|
||||||
|
:param chat_id: Chat ID.
|
||||||
|
:param user_id: User ID.
|
||||||
|
:param timeout: Upload timeout (default: 20 seconds).
|
||||||
|
"""
|
||||||
|
|
||||||
|
telegram = self.get_telegram()
|
||||||
|
user = telegram.bot.get_chat_member(chat_id, user_id, timeout=timeout)
|
||||||
|
return TelegramUserResponse(user_id=user.user.id,
|
||||||
|
link=user.user.link,
|
||||||
|
username=user.user.username,
|
||||||
|
first_name=user.user.first_name,
|
||||||
|
last_name=user.user.last_name,
|
||||||
|
is_bot=user.user.is_bot,
|
||||||
|
language_code=user.user.language_code)
|
||||||
|
|
||||||
|
@action
|
||||||
|
def get_chat_administrators(self, chat_id: Union[int, str], timeout: int = 20) -> TelegramUsersResponse:
|
||||||
|
"""
|
||||||
|
Get the list of the administrators of a chat.
|
||||||
|
|
||||||
|
:param chat_id: Chat ID.
|
||||||
|
:param timeout: Upload timeout (default: 20 seconds).
|
||||||
|
"""
|
||||||
|
|
||||||
|
telegram = self.get_telegram()
|
||||||
|
admins = telegram.bot.get_chat_administrators(chat_id, timeout=timeout)
|
||||||
|
return TelegramUsersResponse([
|
||||||
|
TelegramUserResponse(
|
||||||
|
user_id=user.user.id,
|
||||||
|
link=user.user.link,
|
||||||
|
username=user.user.username,
|
||||||
|
first_name=user.user.first_name,
|
||||||
|
last_name=user.user.last_name,
|
||||||
|
is_bot=user.user.is_bot,
|
||||||
|
language_code=user.user.language_code,
|
||||||
|
) for user in admins
|
||||||
|
])
|
||||||
|
|
||||||
|
@action
|
||||||
|
def get_chat_members_count(self, chat_id: Union[int, str], timeout: int = 20) -> int:
|
||||||
|
"""
|
||||||
|
Get the number of users in a chat.
|
||||||
|
|
||||||
|
:param chat_id: Chat ID.
|
||||||
|
:param timeout: Upload timeout (default: 20 seconds).
|
||||||
|
"""
|
||||||
|
telegram = self.get_telegram()
|
||||||
|
return telegram.bot.get_chat_members_count(chat_id, timeout=timeout)
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def kick_chat_member(self, chat_id: Union[str, int],
|
def kick_chat_member(self, chat_id: Union[str, int],
|
||||||
user_id: int,
|
user_id: int,
|
||||||
|
|
|
@ -19,6 +19,7 @@ class RedisPlugin(Plugin):
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
|
|
||||||
if not kwargs:
|
if not kwargs:
|
||||||
|
# noinspection PyBroadException
|
||||||
try:
|
try:
|
||||||
redis_backend = get_backend('redis')
|
redis_backend = get_backend('redis')
|
||||||
if redis_backend and redis_backend.redis_args:
|
if redis_backend and redis_backend.redis_args:
|
||||||
|
@ -32,7 +33,7 @@ class RedisPlugin(Plugin):
|
||||||
@action
|
@action
|
||||||
def send_message(self, queue, msg, *args, **kwargs):
|
def send_message(self, queue, msg, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Send a message to a Redis queu.
|
Send a message to a Redis queue.
|
||||||
|
|
||||||
:param queue: Queue name
|
:param queue: Queue name
|
||||||
:type queue: str
|
:type queue: str
|
||||||
|
@ -43,7 +44,8 @@ class RedisPlugin(Plugin):
|
||||||
:param args: Args passed to the Redis constructor (see https://redis-py.readthedocs.io/en/latest/#redis.Redis)
|
:param args: Args passed to the Redis constructor (see https://redis-py.readthedocs.io/en/latest/#redis.Redis)
|
||||||
:type args: list
|
:type args: list
|
||||||
|
|
||||||
:param kwargs: Kwargs passed to the Redis constructor (see https://redis-py.readthedocs.io/en/latest/#redis.Redis)
|
:param kwargs: Kwargs passed to the Redis constructor (see
|
||||||
|
https://redis-py.readthedocs.io/en/latest/#redis.Redis)
|
||||||
:type kwargs: dict
|
:type kwargs: dict
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -66,13 +68,13 @@ class RedisPlugin(Plugin):
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def mset(self, *args, **kwargs):
|
def mset(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
Set key/values based on mapping (wraps MSET)
|
Set key/values based on mapping (wraps MSET)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return self._get_redis().mset(*args, **kwargs)
|
return self._get_redis().mset(**kwargs)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# XXX commit https://github.com/andymccurdy/redis-py/commit/90a52dd5de111f0053bb3ebaa7c78f73a82a1e3e
|
# XXX commit https://github.com/andymccurdy/redis-py/commit/90a52dd5de111f0053bb3ebaa7c78f73a82a1e3e
|
||||||
# broke back-compatibility with the previous way of passing
|
# broke back-compatibility with the previous way of passing
|
||||||
|
@ -106,4 +108,3 @@ class RedisPlugin(Plugin):
|
||||||
|
|
||||||
|
|
||||||
# vim:sw=4:ts=4:et:
|
# vim:sw=4:ts=4:et:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue