Compare commits
127 Commits
3969794075
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
53802728a1
|
|||
|
2cdb4e743f
|
|||
|
98fbbf0127
|
|||
|
856d53de1c
|
|||
|
5e8a2b65f5
|
|||
|
3b0bfb4880
|
|||
|
a49e727e31
|
|||
|
c78522d46b
|
|||
|
c4964105b4
|
|||
|
3396bc6f18
|
|||
|
c1f4abc541
|
|||
|
c4a822e45d
|
|||
|
6b4a95be36
|
|||
|
beaf3f8516
|
|||
|
fc1f087d4a
|
|||
|
aeac4aea52
|
|||
|
5ab22909cf
|
|||
|
9094955812
|
|||
|
173783e154
|
|||
|
92a986d090
|
|||
|
3e6e364336
|
|||
|
f0a4c914e4
|
|||
|
80a1440e75
|
|||
|
b978022658
|
|||
|
50f561e7f9
|
|||
|
a9b785f49d
|
|||
|
b7d08ab2ba
|
|||
|
d362ec496b
|
|||
|
0bfc1e157b
|
|||
|
bc40957b27
|
|||
|
45117610f9
|
|||
|
f91661927e
|
|||
|
12f3a2cc73
|
|||
|
25abb80343
|
|||
|
76ea65a660
|
|||
|
e254dbf42a
|
|||
|
b7b91a65ea
|
|||
|
abebff43d9
|
|||
|
a460f71b69
|
|||
|
6ad5ec2865
|
|||
|
cfae729270
|
|||
|
dc9c2a7b14
|
|||
|
a3cc676432
|
|||
|
15a7a58537
|
|||
|
ea30fd39cf
|
|||
|
a5cabdd102
|
|||
|
89fa73d1a5
|
|||
|
4b22658bf5
|
|||
|
bce8cff3cf
|
|||
|
ea07aa47cf
|
|||
|
d49bab54ca
|
|||
|
83d01e4da9
|
|||
|
59dde0d25e
|
|||
|
713f4ffd0e
|
|||
|
51bc95332f
|
|||
|
92758d923c
|
|||
|
946e2a881f
|
|||
|
|
0f4d31892f
|
||
|
|
c4eaa0b9db | ||
|
|
21214feb0a | ||
|
|
f7ee5b71a1 | ||
|
|
fb58c0239d | ||
|
|
c848bfc228 | ||
|
|
f823057cbe | ||
|
|
d7a1acd23b | ||
|
|
70053c9279 | ||
|
|
1c76c7d797 | ||
|
|
dfffbff7c6 | ||
|
|
a4b1ed09a2 | ||
|
|
a1bd681cbf | ||
|
|
9c57677320 | ||
|
|
956e982157 | ||
|
|
4bd10894a8 | ||
|
|
89a9863510 | ||
|
|
ed36e53a28 | ||
|
|
8977e0fbc3 | ||
|
|
cf7e0c740b | ||
|
|
12b18cff58 | ||
|
|
3160723aa7 | ||
|
|
8e2feb5ac2 | ||
|
|
cbc7424a97 | ||
|
|
1e7c384b6d | ||
|
|
7cc2e02f47 | ||
|
|
6315c0dcc2 | ||
|
|
f06c525f5b | ||
|
|
ea5c63c1f8 | ||
|
|
ea549b63c8 | ||
|
|
e63b0f9265 | ||
|
|
cb9310437f | ||
|
|
5bc58dd7d5 | ||
|
|
5d35579e10 | ||
|
|
b0132e0b30 | ||
|
|
49ecee63d0 | ||
|
|
273eda2b67 | ||
|
|
b12f653096 | ||
|
|
05878f3fbd | ||
|
|
c583c3c3b0 | ||
|
|
2d40903069 | ||
|
|
217a445a65 | ||
|
|
b68dbe7a07 | ||
|
|
258ca9f6ef | ||
|
|
3648a36636 | ||
|
|
ef99493c7f | ||
|
|
841f7f0c8d | ||
|
|
23882e5b3b | ||
|
|
6ba21f0115 | ||
|
|
ca6dca3cb7 | ||
|
|
9072c3abe5 | ||
|
|
e74e38c6ae | ||
|
|
7a23045479 | ||
|
|
5ef449a542 | ||
|
|
a2c83f8d9c | ||
|
|
dddaf20ea2 | ||
|
|
a828bb5d3c | ||
|
|
25f5514dff | ||
|
|
34f802732b | ||
|
|
f6466b0540 | ||
|
|
7565df17ba | ||
|
|
4be33370b9 | ||
|
|
cf3f7a88fb | ||
|
|
a4d464da58 | ||
|
|
83c0a91919 | ||
|
|
85a5ce3882 | ||
|
|
77405d2dd3 | ||
|
|
1e2316e748 | ||
|
|
16014c5a42 | ||
|
|
f0be5b5ff2 |
@@ -11,7 +11,7 @@ __author__ = "Davide Testa"
|
||||
__email__ = "davide@davte.it"
|
||||
__credits__ = ["Marco Origlia", "Nick Lee @Nickoala"]
|
||||
__license__ = "GNU General Public License v3.0"
|
||||
__version__ = "2.9.11"
|
||||
__version__ = "2.10.6"
|
||||
__maintainer__ = "Davide Testa"
|
||||
__contact__ = "t.me/davte"
|
||||
|
||||
|
||||
@@ -13,10 +13,12 @@ import asyncio
|
||||
import datetime
|
||||
import json
|
||||
import logging
|
||||
import platform
|
||||
import re
|
||||
import types
|
||||
|
||||
from collections import OrderedDict
|
||||
from importlib.metadata import version as get_package_version_from_metadata
|
||||
from typing import Union, List, Tuple
|
||||
|
||||
# Third party modules
|
||||
@@ -27,8 +29,8 @@ from davtelepot.messages import default_admin_messages, default_talk_messages
|
||||
from davtelepot.bot import Bot
|
||||
from davtelepot.utilities import (
|
||||
async_wrapper, CachedPage, Confirmator, extract, get_cleaned_text,
|
||||
get_user, clean_html_string, line_drawing_unordered_list, make_button,
|
||||
make_inline_keyboard, remove_html_tags, send_part_of_text_file,
|
||||
get_secure_key, get_user, clean_html_string, line_drawing_unordered_list,
|
||||
make_button, make_inline_keyboard, remove_html_tags, send_part_of_text_file,
|
||||
send_csv_file, make_lines_of_buttons, join_path
|
||||
)
|
||||
|
||||
@@ -43,6 +45,13 @@ variable_regex = re.compile(r"(?P<name>[a-zA-Z]\w*)\s*=\s*"
|
||||
r"\"[^\"]*\")")
|
||||
|
||||
|
||||
def get_package_version(package: types.ModuleType):
|
||||
"""Get version of given package."""
|
||||
if hasattr(package, '__version__'):
|
||||
return package.__version__
|
||||
return get_package_version_from_metadata(package.__name__)
|
||||
|
||||
|
||||
async def _forward_to(update,
|
||||
bot: Bot,
|
||||
sender,
|
||||
@@ -223,7 +232,7 @@ def get_talk_panel(bot: Bot,
|
||||
return text, reply_markup
|
||||
|
||||
|
||||
async def _talk_command(bot: Bot,
|
||||
async def talk_command(bot: Bot,
|
||||
update,
|
||||
user_record):
|
||||
text = get_cleaned_text(
|
||||
@@ -343,7 +352,7 @@ async def end_session(bot: Bot,
|
||||
return
|
||||
|
||||
|
||||
async def _talk_button(bot: Bot,
|
||||
async def talk_button(bot: Bot,
|
||||
update,
|
||||
user_record,
|
||||
data):
|
||||
@@ -353,7 +362,7 @@ async def _talk_button(bot: Bot,
|
||||
if command == 'search':
|
||||
bot.set_individual_text_message_handler(
|
||||
await async_wrapper(
|
||||
_talk_command,
|
||||
talk_command,
|
||||
),
|
||||
update
|
||||
)
|
||||
@@ -426,7 +435,7 @@ async def _talk_button(bot: Bot,
|
||||
return result
|
||||
|
||||
|
||||
async def _restart_command(bot: Bot,
|
||||
async def restart_command(bot: Bot,
|
||||
update,
|
||||
user_record):
|
||||
with bot.db as db:
|
||||
@@ -453,7 +462,7 @@ async def _restart_command(bot: Bot,
|
||||
return
|
||||
|
||||
|
||||
async def _stop_command(bot: Bot,
|
||||
async def stop_command(bot: Bot,
|
||||
update,
|
||||
user_record):
|
||||
text = bot.get_message(
|
||||
@@ -495,7 +504,7 @@ async def stop_bots(bot: Bot):
|
||||
return
|
||||
|
||||
|
||||
async def _stop_button(bot: Bot,
|
||||
async def stop_button(bot: Bot,
|
||||
update,
|
||||
user_record,
|
||||
data: List[Union[int, str]]):
|
||||
@@ -535,7 +544,7 @@ async def _stop_button(bot: Bot,
|
||||
return result
|
||||
|
||||
|
||||
async def _send_bot_database(bot: Bot, user_record: OrderedDict, language: str):
|
||||
async def send_bot_database(bot: Bot, user_record: OrderedDict, language: str):
|
||||
if not all(
|
||||
[
|
||||
bot.db_url.endswith('.db'),
|
||||
@@ -562,7 +571,7 @@ async def _send_bot_database(bot: Bot, user_record: OrderedDict, language: str):
|
||||
)
|
||||
|
||||
|
||||
async def _query_command(bot, update, user_record):
|
||||
async def query_command(bot, update, user_record):
|
||||
query = get_cleaned_text(
|
||||
update,
|
||||
bot,
|
||||
@@ -640,7 +649,7 @@ async def _query_command(bot, update, user_record):
|
||||
)
|
||||
|
||||
|
||||
async def _query_button(bot, update, user_record, data):
|
||||
async def query_button(bot, update, user_record, data):
|
||||
result, text, reply_markup = '', '', None
|
||||
command = data[0] if len(data) else 'default'
|
||||
error_message = bot.get_message(
|
||||
@@ -677,7 +686,7 @@ async def _query_button(bot, update, user_record, data):
|
||||
return result
|
||||
|
||||
|
||||
async def _log_command(bot, update, user_record):
|
||||
async def log_command(bot, update, user_record):
|
||||
if bot.log_file_path is None:
|
||||
return bot.get_message(
|
||||
'admin', 'log_command', 'no_log',
|
||||
@@ -730,7 +739,7 @@ async def _log_command(bot, update, user_record):
|
||||
return
|
||||
|
||||
|
||||
async def _errors_command(bot, update, user_record):
|
||||
async def errors_command(bot, update, user_record):
|
||||
# Always send errors log file in private chat
|
||||
chat_id = update['from']['id']
|
||||
if bot.errors_file_path is None:
|
||||
@@ -774,7 +783,7 @@ async def _errors_command(bot, update, user_record):
|
||||
return
|
||||
|
||||
|
||||
async def _maintenance_command(bot, update, user_record):
|
||||
async def maintenance_command(bot, update, user_record):
|
||||
maintenance_message = get_cleaned_text(update, bot, ['maintenance'])
|
||||
if maintenance_message.startswith('{'):
|
||||
maintenance_message = json.loads(maintenance_message)
|
||||
@@ -864,7 +873,12 @@ async def get_new_versions(bot: Bot,
|
||||
"skipping...")
|
||||
continue
|
||||
new_version = web_page['info']['version']
|
||||
current_version = package.__version__
|
||||
try:
|
||||
current_version = get_package_version(package)
|
||||
except TypeError:
|
||||
current_version = "NA"
|
||||
logging.error("Could not get current version of "
|
||||
"package %s", package.__name__)
|
||||
notification_record = bot.db['updates_notifications'].find_one(
|
||||
package=package.__name__,
|
||||
order_by=['-id'],
|
||||
@@ -883,7 +897,7 @@ async def get_new_versions(bot: Bot,
|
||||
return news
|
||||
|
||||
|
||||
async def _version_command(bot: Bot, update: dict,
|
||||
async def version_command(bot: Bot, update: dict,
|
||||
user_record: OrderedDict, language: str):
|
||||
last_commit = await get_last_commit()
|
||||
text = bot.get_message(
|
||||
@@ -891,9 +905,10 @@ async def _version_command(bot: Bot, update: dict,
|
||||
last_commit=last_commit,
|
||||
update=update, user_record=user_record
|
||||
) + '\n\n'
|
||||
text += f'<b>Python: </b> <code>{platform.python_version()}</code>\n'
|
||||
text += '\n'.join(
|
||||
f"<b>{package.__name__}</b>: "
|
||||
f"<code>{package.__version__}</code>"
|
||||
f"<code>{get_package_version(package)}</code>"
|
||||
for package in bot.packages
|
||||
)
|
||||
temporary_message = await bot.send_message(
|
||||
@@ -937,7 +952,7 @@ async def notify_new_version(bot: Bot):
|
||||
order_by=['-id']
|
||||
)
|
||||
current_versions = {
|
||||
f"{package.__name__}_version": package.__version__
|
||||
f"{package.__name__}_version": get_package_version(package)
|
||||
for package in bot.packages
|
||||
}
|
||||
current_versions['last_commit'] = last_commit
|
||||
@@ -1032,7 +1047,7 @@ async def get_package_updates(bot: Bot,
|
||||
await asyncio.sleep(monitoring_interval)
|
||||
|
||||
|
||||
async def _send_start_messages(bot: Bot):
|
||||
async def send_start_messages(bot: Bot):
|
||||
"""Send restart messages at restart."""
|
||||
for restart_message in bot.db['restart_messages'].find(sent=None):
|
||||
asyncio.ensure_future(
|
||||
@@ -1060,7 +1075,7 @@ async def _send_start_messages(bot: Bot):
|
||||
return
|
||||
|
||||
|
||||
async def _load_talking_sessions(bot: Bot):
|
||||
async def load_talking_sessions(bot: Bot):
|
||||
sessions = []
|
||||
for session in bot.db.query(
|
||||
"""SELECT *
|
||||
@@ -1139,7 +1154,7 @@ def get_custom_commands(bot: Bot, language: str = None) -> List[dict]:
|
||||
)
|
||||
|
||||
|
||||
async def _father_command(bot, language):
|
||||
async def father_command(bot, language):
|
||||
modes = [
|
||||
{
|
||||
key: (
|
||||
@@ -1443,12 +1458,12 @@ async def edit_bot_father_settings_via_message(bot: Bot,
|
||||
return result, text, reply_markup
|
||||
|
||||
|
||||
async def _father_button(bot: Bot, user_record: OrderedDict,
|
||||
async def father_button(bot: Bot, user_record: OrderedDict,
|
||||
language: str, data: list):
|
||||
"""Handle BotFather button.
|
||||
|
||||
Operational modes
|
||||
- main: back to main page (see _father_command)
|
||||
- main: back to main page (see `father_command`)
|
||||
- get: show commands stored by @BotFather
|
||||
- set: edit commands stored by @BotFather
|
||||
"""
|
||||
@@ -1542,7 +1557,7 @@ async def _father_button(bot: Bot, user_record: OrderedDict,
|
||||
elif command == 'main':
|
||||
return dict(
|
||||
text='',
|
||||
edit=(await _father_command(bot=bot, language=language))
|
||||
edit=(await father_command(bot=bot, language=language))
|
||||
)
|
||||
elif command == 'set':
|
||||
stored_commands = await bot.getMyCommands()
|
||||
@@ -1810,7 +1825,7 @@ async def _father_button(bot: Bot, user_record: OrderedDict,
|
||||
return result
|
||||
|
||||
|
||||
async def _config_command(bot: Bot, update: dict,
|
||||
async def config_command(bot: Bot, update: dict,
|
||||
user_record: dict, language: str):
|
||||
text = get_cleaned_text(
|
||||
update,
|
||||
@@ -1844,6 +1859,50 @@ async def _config_command(bot: Bot, update: dict,
|
||||
language=language)
|
||||
|
||||
|
||||
async def become_administrator(bot: Bot, update: dict,
|
||||
user_record: dict, language: str):
|
||||
"""When the bot has no administrator, become one providing a token.
|
||||
|
||||
The token will be printed to the stdout on the machine running the bot.
|
||||
"""
|
||||
if len(bot.administrators) > 0:
|
||||
return
|
||||
def _get_message(*args):
|
||||
return bot.get_message('admin', 'become_admin', *args,
|
||||
update=update, user_record=user_record,
|
||||
language=language)
|
||||
token = get_cleaned_text(update=update, bot=bot,
|
||||
replace=['become_administrator',
|
||||
'00become_administrator'],
|
||||
strip='/ @_')
|
||||
if token != bot.administration_token:
|
||||
return _get_message('wrong_token')
|
||||
with bot.db as db:
|
||||
db['users'].update({**user_record, 'privileges': 1},
|
||||
['id'])
|
||||
return _get_message('success')
|
||||
|
||||
|
||||
async def create_promotion_command(bot: Bot):
|
||||
"""If bot has no administrators, users can elevate themselves.
|
||||
|
||||
To do so, they need to provide a token, that will be printed to the stdout
|
||||
of the machine running the bot.
|
||||
"""
|
||||
await bot.get_me()
|
||||
bot.administration_token = get_secure_key(length=10)
|
||||
print(f"To become administrator click "
|
||||
f"https://t.me/{bot.name}?start="
|
||||
f"00become_administrator_{bot.administration_token}")
|
||||
@bot.command(command='become_administrator',
|
||||
authorization_level='everybody',
|
||||
aliases=['00become_administrator'])
|
||||
async def _become_administrator(bot, update, user_record, language):
|
||||
return await become_administrator(bot=bot, update=update,
|
||||
user_record=user_record,
|
||||
language=language)
|
||||
|
||||
|
||||
def init(telegram_bot: Bot,
|
||||
talk_messages: dict = None,
|
||||
admin_messages: dict = None,
|
||||
@@ -1907,16 +1966,16 @@ def init(telegram_bot: Bot,
|
||||
|
||||
# Tasks to complete before starting bot
|
||||
@telegram_bot.additional_task(when='BEFORE')
|
||||
async def load_talking_sessions():
|
||||
return await _load_talking_sessions(bot=telegram_bot)
|
||||
async def _load_talking_sessions():
|
||||
return await load_talking_sessions(bot=telegram_bot)
|
||||
|
||||
@telegram_bot.additional_task(when='BEFORE', bot=telegram_bot)
|
||||
async def notify_version(bot):
|
||||
return await notify_new_version(bot=bot)
|
||||
|
||||
@telegram_bot.additional_task('BEFORE')
|
||||
async def send_restart_messages():
|
||||
return await _send_start_messages(bot=telegram_bot)
|
||||
async def _send_start_messages():
|
||||
return await send_start_messages(bot=telegram_bot)
|
||||
|
||||
# Administration commands
|
||||
@telegram_bot.command(command='/db',
|
||||
@@ -1925,8 +1984,8 @@ def init(telegram_bot: Bot,
|
||||
description=admin_messages[
|
||||
'db_command']['description'],
|
||||
authorization_level='admin')
|
||||
async def send_bot_database(bot, user_record, language):
|
||||
return await _send_bot_database(bot=bot,
|
||||
async def _send_bot_database(bot, user_record, language):
|
||||
return await send_bot_database(bot=bot,
|
||||
user_record=user_record,
|
||||
language=language)
|
||||
|
||||
@@ -1936,8 +1995,8 @@ def init(telegram_bot: Bot,
|
||||
description=admin_messages[
|
||||
'errors_command']['description'],
|
||||
authorization_level='admin')
|
||||
async def errors_command(bot, update, user_record):
|
||||
return await _errors_command(bot, update, user_record)
|
||||
async def _errors_command(bot, update, user_record):
|
||||
return await errors_command(bot, update, user_record)
|
||||
|
||||
@telegram_bot.command(command='/father',
|
||||
aliases=[],
|
||||
@@ -1948,14 +2007,14 @@ def init(telegram_bot: Bot,
|
||||
if key in ('description', )
|
||||
},
|
||||
authorization_level='admin')
|
||||
async def father_command(bot, language):
|
||||
return await _father_command(bot=bot, language=language)
|
||||
async def _father_command(bot, language):
|
||||
return await father_command(bot=bot, language=language)
|
||||
|
||||
@telegram_bot.button(prefix='father:///',
|
||||
separator='|',
|
||||
authorization_level='admin')
|
||||
async def query_button(bot, user_record, language, data):
|
||||
return await _father_button(bot=bot,
|
||||
async def _father_button(bot, user_record, language, data):
|
||||
return await father_button(bot=bot,
|
||||
user_record=user_record,
|
||||
language=language,
|
||||
data=data)
|
||||
@@ -1966,16 +2025,16 @@ def init(telegram_bot: Bot,
|
||||
description=admin_messages[
|
||||
'log_command']['description'],
|
||||
authorization_level='admin')
|
||||
async def log_command(bot, update, user_record):
|
||||
return await _log_command(bot, update, user_record)
|
||||
async def _log_command(bot, update, user_record):
|
||||
return await log_command(bot, update, user_record)
|
||||
|
||||
@telegram_bot.command(command='/maintenance', aliases=[],
|
||||
show_in_keyboard=False,
|
||||
description=admin_messages[
|
||||
'maintenance_command']['description'],
|
||||
authorization_level='admin')
|
||||
async def maintenance_command(bot, update, user_record):
|
||||
return await _maintenance_command(bot, update, user_record)
|
||||
async def _maintenance_command(bot, update, user_record):
|
||||
return await maintenance_command(bot, update, user_record)
|
||||
|
||||
@telegram_bot.command(command='/query',
|
||||
aliases=[],
|
||||
@@ -1983,16 +2042,16 @@ def init(telegram_bot: Bot,
|
||||
description=admin_messages[
|
||||
'query_command']['description'],
|
||||
authorization_level='admin')
|
||||
async def query_command(bot, update, user_record):
|
||||
return await _query_command(bot, update, user_record)
|
||||
async def _query_command(bot, update, user_record):
|
||||
return await query_command(bot, update, user_record)
|
||||
|
||||
@telegram_bot.button(prefix='db_query:///',
|
||||
separator='|',
|
||||
description=admin_messages[
|
||||
'query_command']['description'],
|
||||
authorization_level='admin')
|
||||
async def query_button(bot, update, user_record, data):
|
||||
return await _query_button(bot, update, user_record, data)
|
||||
async def _query_button(bot, update, user_record, data):
|
||||
return await query_button(bot, update, user_record, data)
|
||||
|
||||
@telegram_bot.command(command='/restart',
|
||||
aliases=[],
|
||||
@@ -2000,8 +2059,8 @@ def init(telegram_bot: Bot,
|
||||
description=admin_messages[
|
||||
'restart_command']['description'],
|
||||
authorization_level='admin')
|
||||
async def restart_command(bot, update, user_record):
|
||||
return await _restart_command(bot, update, user_record)
|
||||
async def _restart_command(bot, update, user_record):
|
||||
return await restart_command(bot, update, user_record)
|
||||
|
||||
@telegram_bot.command(command='/select',
|
||||
aliases=[],
|
||||
@@ -2009,8 +2068,8 @@ def init(telegram_bot: Bot,
|
||||
description=admin_messages[
|
||||
'select_command']['description'],
|
||||
authorization_level='admin')
|
||||
async def select_command(bot, update, user_record):
|
||||
return await _query_command(bot, update, user_record)
|
||||
async def _select_command(bot, update, user_record):
|
||||
return await query_command(bot, update, user_record)
|
||||
|
||||
@telegram_bot.command(command='/stop',
|
||||
aliases=[],
|
||||
@@ -2018,16 +2077,16 @@ def init(telegram_bot: Bot,
|
||||
description=admin_messages[
|
||||
'stop_command']['description'],
|
||||
authorization_level='admin')
|
||||
async def stop_command(bot, update, user_record):
|
||||
return await _stop_command(bot, update, user_record)
|
||||
async def _stop_command(bot, update, user_record):
|
||||
return await stop_command(bot, update, user_record)
|
||||
|
||||
@telegram_bot.button(prefix='stop:///',
|
||||
separator='|',
|
||||
description=admin_messages[
|
||||
'stop_command']['description'],
|
||||
authorization_level='admin')
|
||||
async def stop_button(bot, update, user_record, data):
|
||||
return await _stop_button(bot, update, user_record, data)
|
||||
async def _stop_button(bot, update, user_record, data):
|
||||
return await stop_button(bot, update, user_record, data)
|
||||
|
||||
@telegram_bot.command(command='/talk',
|
||||
aliases=[],
|
||||
@@ -2035,14 +2094,14 @@ def init(telegram_bot: Bot,
|
||||
description=admin_messages[
|
||||
'talk_command']['description'],
|
||||
authorization_level='admin')
|
||||
async def talk_command(bot, update, user_record):
|
||||
return await _talk_command(bot, update, user_record)
|
||||
async def _talk_command(bot, update, user_record):
|
||||
return await talk_command(bot, update, user_record)
|
||||
|
||||
@telegram_bot.button(prefix='talk:///',
|
||||
separator='|',
|
||||
authorization_level='admin')
|
||||
async def talk_button(bot, update, user_record, data):
|
||||
return await _talk_button(bot, update, user_record, data)
|
||||
async def _talk_button(bot, update, user_record, data):
|
||||
return await talk_button(bot, update, user_record, data)
|
||||
|
||||
@telegram_bot.command(command='/version',
|
||||
aliases=[],
|
||||
@@ -2053,8 +2112,8 @@ def init(telegram_bot: Bot,
|
||||
},
|
||||
show_in_keyboard=False,
|
||||
authorization_level='admin')
|
||||
async def version_command(bot, update, user_record, language):
|
||||
return await _version_command(bot=bot,
|
||||
async def _version_command(bot, update, user_record, language):
|
||||
return await version_command(bot=bot,
|
||||
update=update,
|
||||
user_record=user_record,
|
||||
language=language)
|
||||
@@ -2068,8 +2127,11 @@ def init(telegram_bot: Bot,
|
||||
},
|
||||
show_in_keyboard=False,
|
||||
authorization_level='admin')
|
||||
async def config_command(bot, update, user_record, language):
|
||||
return await _config_command(bot=bot,
|
||||
async def _config_command(bot, update, user_record, language):
|
||||
return await config_command(bot=bot,
|
||||
update=update,
|
||||
user_record=user_record,
|
||||
language=language)
|
||||
|
||||
if len(telegram_bot.administrators) == 0:
|
||||
asyncio.ensure_future(create_promotion_command(bot=telegram_bot))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,34 +2,6 @@
|
||||
|
||||
camelCase methods mirror API directly, while snake_case ones act as middleware
|
||||
someway.
|
||||
|
||||
Usage
|
||||
```
|
||||
import sys
|
||||
|
||||
from davtelepot.bot import Bot
|
||||
|
||||
from data.passwords import my_token, my_other_token
|
||||
|
||||
long_polling_bot = Bot(token=my_token, database_url='my_db')
|
||||
webhook_bot = Bot(token=my_other_token, hostname='example.com',
|
||||
certificate='path/to/certificate.pem',
|
||||
database_url='my_other_db')
|
||||
|
||||
@long_polling_bot.command('/foo')
|
||||
async def foo_command(bot, update, user_record, language):
|
||||
return "Bar!"
|
||||
|
||||
@webhook_bot.command('/bar')
|
||||
async def bar_command(bot, update, user_record, language):
|
||||
return "Foo!"
|
||||
|
||||
exit_state = Bot.run(
|
||||
local_host='127.0.0.5',
|
||||
port=8552
|
||||
)
|
||||
sys.exit(exit_state)
|
||||
```
|
||||
"""
|
||||
|
||||
# Standard library modules
|
||||
@@ -49,7 +21,9 @@ from typing import Callable, List, Union, Dict
|
||||
import aiohttp.web
|
||||
|
||||
# Project modules
|
||||
from davtelepot.api import TelegramBot, TelegramError
|
||||
from davtelepot.api import (
|
||||
LinkPreviewOptions, ReplyParameters, TelegramBot, TelegramError
|
||||
)
|
||||
from davtelepot.database import ObjectWithDatabase
|
||||
from davtelepot.languages import MultiLanguageObject
|
||||
from davtelepot.messages import davtelepot_messages
|
||||
@@ -1319,19 +1293,21 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
|
||||
async def send_message(self, chat_id: Union[int, str] = None,
|
||||
text: str = None,
|
||||
message_thread_id: int = None,
|
||||
entities: List[dict] = None,
|
||||
parse_mode: str = 'HTML',
|
||||
message_thread_id: int = None,
|
||||
link_preview_options: LinkPreviewOptions = None,
|
||||
disable_notification: bool = None,
|
||||
protect_content: bool = None,
|
||||
disable_web_page_preview: bool = None,
|
||||
disable_notification: bool = None,
|
||||
reply_to_message_id: int = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
reply_markup=None,
|
||||
update: dict = None,
|
||||
reply_to_update: bool = False,
|
||||
send_default_keyboard: bool = True,
|
||||
user_record: OrderedDict = None):
|
||||
user_record: OrderedDict = None,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
reply_markup=None):
|
||||
"""Send text via message(s).
|
||||
|
||||
This method wraps lower-level `TelegramBot.sendMessage` method.
|
||||
@@ -1352,6 +1328,10 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
user_record = self.db['users'].find_one(telegram_id=chat_id)
|
||||
if reply_to_update and 'message_id' in update:
|
||||
reply_to_message_id = update['message_id']
|
||||
if disable_web_page_preview:
|
||||
if link_preview_options is None:
|
||||
link_preview_options = LinkPreviewOptions()
|
||||
link_preview_options['is_disabled'] = True
|
||||
if (
|
||||
send_default_keyboard
|
||||
and reply_markup is None
|
||||
@@ -1395,19 +1375,27 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
limit=self.__class__.TELEGRAM_MESSAGES_MAX_LEN - 100,
|
||||
parse_mode=parse_mode
|
||||
)
|
||||
if reply_to_message_id:
|
||||
if reply_parameters is None:
|
||||
reply_parameters = ReplyParameters(message_id=reply_to_message_id)
|
||||
reply_parameters['message_id'] = reply_to_message_id
|
||||
if allow_sending_without_reply:
|
||||
reply_parameters['allow_sending_without_reply'] = allow_sending_without_reply
|
||||
if reply_to_update and 'chat' in update and 'id' in update['chat']:
|
||||
if update['chat']['id'] != chat_id:
|
||||
reply_parameters['chat_id'] = update['chat']['id']
|
||||
for text_chunk, is_last in text_chunks:
|
||||
_reply_markup = (reply_markup if is_last else None)
|
||||
sent_message_update = await self.sendMessage(
|
||||
chat_id=chat_id,
|
||||
text=text_chunk,
|
||||
message_thread_id=message_thread_id,
|
||||
parse_mode=parse_mode,
|
||||
entities=entities,
|
||||
message_thread_id=message_thread_id,
|
||||
protect_content=protect_content,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
link_preview_options=link_preview_options,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
allow_sending_without_reply=allow_sending_without_reply,
|
||||
protect_content=protect_content,
|
||||
reply_parameters=reply_parameters,
|
||||
reply_markup=_reply_markup
|
||||
)
|
||||
return sent_message_update
|
||||
@@ -1431,6 +1419,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
parse_mode: str = 'HTML',
|
||||
entities: List[dict] = None,
|
||||
disable_web_page_preview: bool = None,
|
||||
link_preview_options: LinkPreviewOptions = None,
|
||||
allow_sending_without_reply: bool = None,
|
||||
reply_markup=None,
|
||||
update: dict = None):
|
||||
@@ -1463,6 +1452,10 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
)
|
||||
):
|
||||
if i == 0:
|
||||
if disable_web_page_preview:
|
||||
if link_preview_options is None:
|
||||
link_preview_options = LinkPreviewOptions()
|
||||
link_preview_options['is_disabled'] = True
|
||||
edited_message = await self.editMessageText(
|
||||
text=text_chunk,
|
||||
chat_id=chat_id,
|
||||
@@ -1470,7 +1463,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
inline_message_id=inline_message_id,
|
||||
parse_mode=parse_mode,
|
||||
entities=entities,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
link_preview_options=link_preview_options,
|
||||
reply_markup=(reply_markup if is_last else None)
|
||||
)
|
||||
if chat_id is None:
|
||||
@@ -1576,6 +1569,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
reply_markup=None,
|
||||
update: dict = None,
|
||||
reply_to_update: bool = False,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
send_default_keyboard: bool = True,
|
||||
use_stored_file_id: bool = True):
|
||||
"""Send photos.
|
||||
@@ -1599,6 +1593,15 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
chat_id = self.get_chat_id(update)
|
||||
if reply_to_update and 'message_id' in update:
|
||||
reply_to_message_id = update['message_id']
|
||||
if reply_to_message_id:
|
||||
if reply_parameters is None:
|
||||
reply_parameters = ReplyParameters(message_id=reply_to_message_id)
|
||||
reply_parameters['message_id'] = reply_to_message_id
|
||||
if allow_sending_without_reply:
|
||||
reply_parameters['allow_sending_without_reply'] = allow_sending_without_reply
|
||||
if reply_to_update and 'chat' in update and 'id' in update['chat']:
|
||||
if update['chat']['id'] != chat_id:
|
||||
reply_parameters['chat_id'] = update['chat']['id']
|
||||
if (
|
||||
send_default_keyboard
|
||||
and reply_markup is None
|
||||
@@ -1652,8 +1655,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
parse_mode=parse_mode,
|
||||
caption_entities=caption_entities,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
allow_sending_without_reply=allow_sending_without_reply,
|
||||
reply_parameters=reply_parameters,
|
||||
reply_markup=reply_markup
|
||||
)
|
||||
if isinstance(sent_update, Exception):
|
||||
@@ -1701,6 +1703,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
reply_markup=None,
|
||||
update: dict = None,
|
||||
reply_to_update: bool = False,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
send_default_keyboard: bool = True,
|
||||
use_stored_file_id: bool = True):
|
||||
"""Send audio files.
|
||||
@@ -1724,6 +1727,15 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
chat_id = self.get_chat_id(update)
|
||||
if reply_to_update and 'message_id' in update:
|
||||
reply_to_message_id = update['message_id']
|
||||
if reply_to_message_id:
|
||||
if reply_parameters is None:
|
||||
reply_parameters = ReplyParameters(message_id=reply_to_message_id)
|
||||
reply_parameters['message_id'] = reply_to_message_id
|
||||
if allow_sending_without_reply:
|
||||
reply_parameters['allow_sending_without_reply'] = allow_sending_without_reply
|
||||
if reply_to_update and 'chat' in update and 'id' in update['chat']:
|
||||
if update['chat']['id'] != chat_id:
|
||||
reply_parameters['chat_id'] = update['chat']['id']
|
||||
if (
|
||||
send_default_keyboard
|
||||
and reply_markup is None
|
||||
@@ -1781,8 +1793,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
title=title,
|
||||
thumbnail=thumbnail,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
allow_sending_without_reply=allow_sending_without_reply,
|
||||
reply_parameters=reply_parameters,
|
||||
reply_markup=reply_markup
|
||||
)
|
||||
if isinstance(sent_update, Exception):
|
||||
@@ -1826,6 +1837,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
reply_markup=None,
|
||||
update: dict = None,
|
||||
reply_to_update: bool = False,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
send_default_keyboard: bool = True,
|
||||
use_stored_file_id: bool = True):
|
||||
"""Send voice messages.
|
||||
@@ -1849,6 +1861,15 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
chat_id = self.get_chat_id(update)
|
||||
if reply_to_update and 'message_id' in update:
|
||||
reply_to_message_id = update['message_id']
|
||||
if reply_to_message_id:
|
||||
if reply_parameters is None:
|
||||
reply_parameters = ReplyParameters(message_id=reply_to_message_id)
|
||||
reply_parameters['message_id'] = reply_to_message_id
|
||||
if allow_sending_without_reply:
|
||||
reply_parameters['allow_sending_without_reply'] = allow_sending_without_reply
|
||||
if reply_to_update and 'chat' in update and 'id' in update['chat']:
|
||||
if update['chat']['id'] != chat_id:
|
||||
reply_parameters['chat_id'] = update['chat']['id']
|
||||
if (
|
||||
send_default_keyboard
|
||||
and reply_markup is None
|
||||
@@ -1903,8 +1924,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
caption_entities=caption_entities,
|
||||
duration=duration,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
allow_sending_without_reply=allow_sending_without_reply,
|
||||
reply_parameters=reply_parameters,
|
||||
reply_markup=reply_markup
|
||||
)
|
||||
if isinstance(sent_update, Exception):
|
||||
@@ -1951,6 +1971,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
document_name: str = None,
|
||||
update: dict = None,
|
||||
reply_to_update: bool = False,
|
||||
reply_parameters: ReplyParameters = None,
|
||||
send_default_keyboard: bool = True,
|
||||
use_stored_file_id: bool = False):
|
||||
"""Send a document.
|
||||
@@ -1983,6 +2004,15 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
return
|
||||
if reply_to_update and 'message_id' in update:
|
||||
reply_to_message_id = update['message_id']
|
||||
if reply_to_message_id:
|
||||
if reply_parameters is None:
|
||||
reply_parameters = ReplyParameters(message_id=reply_to_message_id)
|
||||
reply_parameters['message_id'] = reply_to_message_id
|
||||
if allow_sending_without_reply:
|
||||
reply_parameters['allow_sending_without_reply'] = allow_sending_without_reply
|
||||
if reply_to_update and 'chat' in update and 'id' in update['chat']:
|
||||
if update['chat']['id'] != chat_id:
|
||||
reply_parameters['chat_id'] = update['chat']['id']
|
||||
if chat_id > 0:
|
||||
user_record = self.db['users'].find_one(telegram_id=chat_id)
|
||||
language = self.get_language(update=update, user_record=user_record)
|
||||
@@ -2061,7 +2091,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
caption=caption,
|
||||
parse_mode=parse_mode,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
reply_parameters=reply_parameters,
|
||||
reply_markup=reply_markup,
|
||||
update=update,
|
||||
reply_to_update=reply_to_update,
|
||||
@@ -2092,8 +2122,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
caption_entities=caption_entities,
|
||||
disable_content_type_detection=disable_content_type_detection,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
allow_sending_without_reply=allow_sending_without_reply,
|
||||
reply_parameters=reply_parameters,
|
||||
reply_markup=reply_markup
|
||||
)
|
||||
if isinstance(sent_update, Exception):
|
||||
@@ -2127,7 +2156,8 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
return sent_update
|
||||
|
||||
async def download_file(self, file_id,
|
||||
file_name=None, path=None):
|
||||
file_name=None, path=None,
|
||||
prevent_overwriting: bool = False):
|
||||
"""Given a telegram `file_id`, download the related file.
|
||||
|
||||
Telegram may not preserve the original file name and MIME type: the
|
||||
@@ -2151,6 +2181,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
if file_name is None:
|
||||
file_name = get_secure_key(length=10)
|
||||
file_complete_path = os.path.join(path, file_name)
|
||||
if prevent_overwriting:
|
||||
while os.path.exists(file_complete_path):
|
||||
file_complete_path = file_complete_path + '1'
|
||||
try:
|
||||
@@ -3503,7 +3534,7 @@ class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject):
|
||||
Each bot will receive updates via long polling or webhook according to
|
||||
its initialization parameters.
|
||||
A single aiohttp.web.Application instance will be run (cls.app) on
|
||||
local_host:port and it may serve custom-defined routes as well.
|
||||
local_host:port, and it may serve custom-defined routes as well.
|
||||
"""
|
||||
if local_host is not None:
|
||||
cls.local_host = local_host
|
||||
|
||||
@@ -22,6 +22,16 @@ davtelepot_messages = {
|
||||
}
|
||||
|
||||
default_admin_messages = {
|
||||
'become_admin': {
|
||||
'success': {
|
||||
'en': "🎉 You are now administrator! 👑",
|
||||
'it': "🎉 Ora hai diritti di amministrazione! 👑",
|
||||
},
|
||||
'wrong_token': {
|
||||
'en': "❌ Wrong token 🚷",
|
||||
'it': "❌ Password errata 🚷",
|
||||
},
|
||||
},
|
||||
'cancel': {
|
||||
'button': {
|
||||
'en': "↩️ Cancel",
|
||||
|
||||
Reference in New Issue
Block a user