1
0
mirror of https://github.com/eternnoir/pyTelegramBotAPI.git synced 2023-08-10 21:12:57 +03:00

Update util.py

- Removed function `unix_time`
- Added function `escape`
- Added function `user_link`
- Added function `quick_markup`
- Added some type hints
This commit is contained in:
SwissCorePy 2021-06-03 19:51:33 +02:00
parent 9a6ddce8df
commit ed5e5e5077

View File

@ -6,10 +6,11 @@ import threading
import traceback import traceback
import warnings import warnings
import functools import functools
import time from typing import Any, List, Dict
import queue as Queue import queue as Queue
import logging import logging
from telebot import types
try: try:
from PIL import Image from PIL import Image
@ -187,7 +188,7 @@ def pil_image_to_file(image, extension='JPEG', quality='web_low'):
else: else:
raise RuntimeError('PIL module is not imported') raise RuntimeError('PIL module is not imported')
def is_command(text): def is_command(text: str) -> bool:
""" """
Checks if `text` is a command. Telegram chat commands start with the '/' character. Checks if `text` is a command. Telegram chat commands start with the '/' character.
:param text: Text to check. :param text: Text to check.
@ -197,7 +198,7 @@ def is_command(text):
return text.startswith('/') return text.startswith('/')
def extract_command(text): def extract_command(text: str) -> str:
""" """
Extracts the command from `text` (minus the '/') if `text` is a command (see is_command). Extracts the command from `text` (minus the '/') if `text` is a command (see is_command).
If `text` is not a command, this function returns None. If `text` is not a command, this function returns None.
@ -215,26 +216,24 @@ def extract_command(text):
return text.split()[0].split('@')[0][1:] if is_command(text) else None return text.split()[0].split('@')[0][1:] if is_command(text) else None
def unix_time(seconds=0, minutes=0, hours=0, days=0): def extract_arguments(text: str) -> str:
""" """
Returns UNIX time + given paramenters Returns the argument after the command.
This is useful to restrict or kick a chat member. Just use it as parameter `until_date`.
Examples: Examples:
bot.kick_chat_member(chat_id, user_id, until_date=unix_time(days=1)): bans a chat member for 1 day extract_arguments("/get name"): 'name'
bot.kick_chat_member(chat_id, user_id, until_date=unix_time(seconds=45)): bans a chat member for 45 seconds extract_arguments("/get"): ''
extract_arguments("/get@botName name"): 'name'
:param seconds: how many seconds from now :param text: String to extract the arguments from a command
:param minutes: how many minutes from now :return: the arguments if `text` is a command (according to is_command), else None.
:param hours: how many hours from now
:param days: how many days from now
:return: UNIX time
""" """
t = seconds + (60 * minutes) + (3600 * hours) + (86400 * days) regexp = re.compile(r"/\w*(@\w*)*\s*([\s\S]*)",re.IGNORECASE)
return (int(t + time.time())) result = regexp.match(text)
return result.group(2) if is_command(text) else None
def split_string(text, chars_per_string): def split_string(text: str, chars_per_string: int) -> List[str]:
""" """
Splits one string into multiple strings, with a maximum amount of `chars_per_string` characters per string. Splits one string into multiple strings, with a maximum amount of `chars_per_string` characters per string.
This is very useful for splitting one giant message into multiples. This is very useful for splitting one giant message into multiples.
@ -246,7 +245,7 @@ def split_string(text, chars_per_string):
return [text[i:i + chars_per_string] for i in range(0, len(text), chars_per_string)] return [text[i:i + chars_per_string] for i in range(0, len(text), chars_per_string)]
def smart_split(text, chars_per_string=MAX_MESSAGE_LENGTH): def smart_split(text: str, chars_per_string: int=MAX_MESSAGE_LENGTH) -> List[str]:
f""" f"""
Splits one string into multiple strings, with a maximum amount of `chars_per_string` characters per string. Splits one string into multiple strings, with a maximum amount of `chars_per_string` characters per string.
This is very useful for splitting one giant message into multiples. This is very useful for splitting one giant message into multiples.
@ -257,7 +256,7 @@ def smart_split(text, chars_per_string=MAX_MESSAGE_LENGTH):
:param chars_per_string: The number of maximum characters per part the text is split to. :param chars_per_string: The number of maximum characters per part the text is split to.
:return: The splitted text as a list of strings. :return: The splitted text as a list of strings.
""" """
def _text_before_last(substr): def _text_before_last(substr: str) -> str:
return substr.join(part.split(substr)[:-1]) + substr return substr.join(part.split(substr)[:-1]) + substr
if chars_per_string > MAX_MESSAGE_LENGTH: chars_per_string = MAX_MESSAGE_LENGTH if chars_per_string > MAX_MESSAGE_LENGTH: chars_per_string = MAX_MESSAGE_LENGTH
@ -277,6 +276,72 @@ def smart_split(text, chars_per_string=MAX_MESSAGE_LENGTH):
parts.append(part) parts.append(part)
text = text[len(part):] text = text[len(part):]
def escape(text: str) -> str:
"""
Replaces the following chars in `text` ('&' with '&amp;', '<' with '&lt;' and '>' with '&gt;').
:param text: the text to escape
:return: the escaped text
"""
chars = {"&": "&amp;", "<": "&lt;", ">": "&gt"}
for old, new in chars.items(): text = text.replace(old, new)
return text
def user_link(user: types.User, include_id: bool=False) -> str:
"""
Returns an HTML user link. This is useful for reports.
Attention: Don't forget to set parse_mode to 'HTML'!
Example:
bot.send_message(your_user_id, user_link(message.from_user) + ' startet the bot!', parse_mode='HTML')
:param user: the user (not the user_id)
:param include_id: include the user_id
:return: HTML user link
"""
name = escape(user.first_name)
return (f"<a href='tg://user?id={user.id}'>{name}</a>"
+ f" (<pre>{user.id}</pre>)" if include_id else "")
def quick_markup(values: Dict[str, Dict[str, Any]], row_width: int=2) -> types.InlineKeyboardMarkup:
"""
Returns a reply markup from a dict in this format: {'text': kwargs}
This is useful to avoid always typing 'btn1 = InlineKeyboardButton(...)' 'btn2 = InlineKeyboardButton(...)'
Example:
quick_markup({
'Twitter': {'url': 'https://twitter.com'},
'Facebook': {'url': 'https://facebook.com'},
'Back': {'callback_data': 'whatever'}
}, row_width=2):
returns an InlineKeyboardMarkup with two buttons in a row, one leading to Twitter, the other to facebook
and a back button below
kwargs can be:
{
'url': None,
'callback_data': None,
'switch_inline_query': None,
'switch_inline_query_current_chat': None,
'callback_game': None,
'pay': None,
'login_url': None
}
:param values: a dict containing all buttons to create in this format: {text: kwargs} {str:}
:return: InlineKeyboardMarkup
"""
markup = types.InlineKeyboardMarkup(row_width=row_width)
buttons = []
for text, kwargs in values.items():
buttons.append(types.InlineKeyboardButton(text=text, **kwargs))
markup.add(*buttons)
return markup
# CREDITS TO http://stackoverflow.com/questions/12317940#answer-12320352 # CREDITS TO http://stackoverflow.com/questions/12317940#answer-12320352
def or_set(self): def or_set(self):
self._set() self._set()
@ -317,22 +382,6 @@ def OrEvent(*events):
changed() changed()
return or_event return or_event
def extract_arguments(text):
"""
Returns the argument after the command.
Examples:
extract_arguments("/get name"): 'name'
extract_arguments("/get"): ''
extract_arguments("/get@botName name"): 'name'
:param text: String to extract the arguments from a command
:return: the arguments if `text` is a command (according to is_command), else None.
"""
regexp = re.compile(r"/\w*(@\w*)*\s*([\s\S]*)",re.IGNORECASE)
result = regexp.match(text)
return result.group(2) if is_command(text) else None
def per_thread(key, construct_value, reset=False): def per_thread(key, construct_value, reset=False):
if reset or not hasattr(thread_local, key): if reset or not hasattr(thread_local, key):