# `7MMM. ,MMF'`7MMM. ,MMF' `7MMM. ,MMF' `7MM
# MMMb dPMM MMMb dPMM MMMb dPMM MM
# M YM ,M MM M YM ,M MM M YM ,M MM ,pW"Wq. ,M""bMM ,pP"Ybd
# M Mb M' MM M Mb M' MM M Mb M' MM 6W' `Wb ,AP MM 8I `"
# M YM.P' MM M YM.P' MM mmmmm M YM.P' MM 8M M8 8MI MM `YMMMa.
# M `YM' MM M `YM' MM M `YM' MM YA. ,A9 `Mb MM L. I8
# .JML. `' .JMML..JML. `' .JMML. .JML. `' .JMML.`Ybmd9' `Wbmd"MML.M9mmmP'
#
# (c) 2023 — licensed under Apache 2.0 — https://www.apache.org/licenses/LICENSE-2.0
# meta pic: https://img.icons8.com/stickers/344/block.png
# meta developer: @mm_mods
__version__ = "1.0.0"
from hikka import loader, utils
from telethon.tl.patched import Message
import logging
from datetime import datetime, timedelta
logger = logging.getLogger(__name__)
# noinspection PyCallingNonCallable
@loader.tds
class ASAPMod(loader.Module):
"""Advanced Sending Automatisation Program"""
strings = {
'name': 'ASAP',
'args?!': '🟥 Arguments needed!',
'incorrecttime': '🟥 Incorrect time!\n{example}',
'taskslist': '📄 Tasks list:\n\n',
'task': 'Task {x}: send {text} to {address} ({at_time}).\n',
'tasklistempty': '🟨 Tasks list is empty!',
'taskadded': '🟩 Task added!\nNext execution: {at_time}, task number: {x}',
'taskremoved': '🟩 Task removed!',
'tasknotfound': '🟥 Task not found!',
'tasklistcleared': '🟩 Tasks list cleared!',
'taskpaused': '🟩 Task paused!',
'allpaused': '🟩 All tasks paused!',
'taskresumed': '🟩 Task resumed!',
'taskpretimeexecuted': '🟩 Task executed!\nNext execution: {at_time}',
'taskreplanned': '🟩 Task replanned!\nNext execution: {at_time}',
'defaultintervalset': '🟩 Default interval set!\n{example}',
'incorrectinterval': '🟥 Incorrect interval!',
'timeformatexample': '🟦 Time format example: 2h — 2 hours, '
'1d 2h 30m — 1 day, 2 hours and 30 minutes, '
'20s — 20 seconds.',
'tzset': '🟩 Timezone set!',
'incorrecttz': '🟥 Incorrect timezone!',
'safetyreasonerror': '🟨 For safety reasons, you can\'t set such short interval!',
}
strings_ru = {
'name': 'ASAP',
'_cls_doc': 'Продвинутая программа автоматизации отправки сообщений',
'args?!': '🟥 Нужны аргументы!',
'incorrecttime': '🟥 Неверное время!\n{example}',
'taskslist': '📄 Список задач:\n\n',
'task': 'Задача {x}: отправить {text} на {address} ({at_time}).'
'\n',
'tasklistempty': '🟨 Список задач пуст!',
'taskadded': '🟩 Задача добавлена!\nСледующее выполнение: {at_time}, номер задачи: {'
'x}',
'taskremoved': '🟩 Задача удалена!',
'tasknotfound': '🟩 Задача не найдена!',
'tasklistcleared': '🟩 Список задач очищен!',
'taskpaused': '🟩 Задача приостановлена!',
'allpaused': '🟩 Все задачи приостановлены!',
'taskresumed': '🟩 Задача возобновлена!',
'taskpretimeexecuted': '🟩 Задача выполнена!\nСледующее выполнение: {at_time}',
'taskreplanned': '🟩 Задача перепланирована!\nСледующее выполнение: {at_time}',
'defaultintervalset': '🟩 Интервал по умолчанию установлен!',
'incorrectinterval': '🟥 Неверный интервал!\n{example}',
'timeformatexample': '🟦 Пример формата времени: 2h — 2 часа, '
'1d 2h 30m — 1 день, 2 часа и 30 минут, '
'20s — 20 секунд.',
'tzset': '🟩 Часовой пояс установлен!',
'incorrecttz': '🟥 Неверный часовой пояс!',
'safetyreasonerror': '🟨 По соображениям безопасности вы не можете установить такой короткий интервал!',
}
strings_de = {
'name': 'ASAP',
'_cls_doc': 'Fortgeschrittenes Programm zur Automatisierung des Nachrichtenversands',
'args?!': '🟥 Argumente benötigt!',
'incorrecttime': '🟥 Falsche Zeit!\n{example}',
'taskslist': '📄 Aufgabenliste:\n\n',
'task': 'Aufgabe {x}: senden {text} zu {address} ({at_time}).\n',
'tasklistempty': '🟨 Aufgabenliste ist leer!',
'taskadded': '🟩 Aufgabe hinzugefügt!\nNächste Ausführung: {at_time}, '
'Aufgabennummer: {x}',
'taskremoved': '🟩 Aufgabe entfernt!',
'tasknotfound': '🟩 Aufgabe nicht gefunden!',
'tasklistcleared': '🟩 Aufgabenliste gelöscht!',
'taskpaused': '🟩 Aufgabe pausiert!',
'allpaused': '🟩 Alle Aufgaben pausiert!',
'taskresumed': '🟩 Aufgabe fortgesetzt!',
'taskpretimeexecuted': '🟩 Aufgabe ausgeführt!\nNächste Ausführung: {at_time}',
'taskreplanned': '🟩 Aufgabe neu geplant!\nNächste Ausführung: {at_time}',
'defaultintervalset': '🟩 Standardintervall gesetzt!',
'incorrectinterval': '🟥 Falsches Intervall!\n{example}',
'timeformatexample': '🟦 Beispiel für das Zeitformat: 2h — 2 Stunden, '
'1d 2h 30m — 1 Tag, 2 Stunden und 30 Minuten, '
'20s — 20 Sekunden.',
'tzset': '🟩 Zeitzone gesetzt!',
'incorrecttz': '🟥 Falsche Zeitzone!',
'safetyreasonerror': '🟨 Aus Sicherheitsgründen können Sie kein so kurzes Intervall festlegen!',
}
async def client_ready(self):
if not self.get('default_interval'):
self.set('default_interval', '2h')
if not self.get('tasks'):
self.set('tasks', {})
if not self.get('tz'):
self.set('tz', 0)
@loader.loop(interval=1, autostart=True)
async def _run_tasks(self):
tasks = self.get('tasks')
if not tasks:
return
for k, task in tasks.items():
if datetime.strptime(task['next_execution'], '%d.%m.%Y %H:%M:%S') <= datetime.now():
await self._run_task(task, k)
@staticmethod
def validate_time(time: str) -> bool:
"""
Validates the time.
:param time: time to validate.
:return: if time is valid or not.
"""
if not time:
return False
args = time.split()
for arg in args:
if not arg[:-1].isdigit():
return False
if arg[-1] not in ['s', 'm', 'h', 'd']:
return False
return True
@staticmethod
def convert_time(time: str) -> timedelta:
"""
Converts time to timedelta.
:param time: time to convert.
:return: timedelta.
"""
args = time.split()
res = timedelta()
for arg in args:
try:
if arg[-1] == 's':
res += timedelta(seconds=int(arg[:-1]))
elif arg[-1] == 'm':
res += timedelta(minutes=int(arg[:-1]))
elif arg[-1] == 'h':
res += timedelta(hours=int(arg[:-1]))
elif arg[-1] == 'd':
res += timedelta(days=int(arg[:-1]))
except ValueError:
pass
return res
@loader.command(
'ataskadd',
ru_doc='Добавить задачу в список задач.\nИспользование: .ataskadd <текст>\n[время]\n[адресат]',
de_doc='Fügen Sie eine Aufgabe zur Aufgabenliste hinzu.\nVerwendung: .ataskadd \n[Zeit]\n[Empfänger]',
)
async def ataskaddcmd(self, m: Message):
"""Add a task to the list of tasks.
Usage: .ataskadd
[time]
[target]"""
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?!'))
args = args.split('\n')
if len(args) == 2:
interval = args[1]
address = m.chat_id
elif len(args) == 3:
interval = args[1]
address = args[2]
else:
interval = self.get('default_interval')
address = m.chat_id
if not self.validate_time(interval):
return await utils.answer(m, self.strings('incorrecttime'))
if self.convert_time(interval) < timedelta(seconds=10):
return await utils.answer(m, self.strings('safetyreasonerror'))
task = {
'text': args[0],
'interval': interval,
'address': address,
'paused': False,
'next_execution': (datetime.now() + self.convert_time(interval)).strftime('%d.%m.%Y %H:%M:%S'),
}
tasks = self.get('tasks')
x = len(tasks) + 1
tasks[str(x)] = task
self.set('tasks', tasks)
await utils.answer(
m, self.strings('taskadded').format(
at_time=task['next_execution'],
x=x
)
)
@loader.command(
'ataskremove',
ru_doc='Удалить задачу из списка задач.\nИспользование: .ataskremove <номер>',
de_doc='Entfernen Sie eine Aufgabe aus der Aufgabenliste.\nVerwendung: .ataskremove ',
)
async def ataskremovecmd(self, m: Message):
"""Remove a task from the list of tasks.
Usage: .ataskremove """
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?!'))
try:
x = int(args)
except ValueError:
return await utils.answer(m, self.strings('args?!'))
x = str(x)
tasks = self.get('tasks')
if x not in tasks:
return await utils.answer(m, self.strings('tasknotfound'))
del tasks[x]
self.set('tasks', tasks)
await utils.answer(m, self.strings('taskremoved'))
@loader.command(
'atasklist',
ru_doc='Показать список задач.',
de_doc='Zeigt die Liste der Aufgaben an.',
)
async def atasklistcmd(self, m: Message):
"""Show the list of tasks."""
tasks = self.get('tasks')
if not tasks:
return await utils.answer(m, self.strings('tasklistempty'))
res = self.strings('taskslist')
for k, task in tasks.items():
res += self.strings('task').format(
x=k if not task['paused'] else f'{k}',
text=task['text'],
address=task['address'],
at_time=datetime.strptime(task['next_execution'], '%d.%m.%Y %H:%M:%S') + timedelta(hours=self.get('tz'))
)
await utils.answer(m, res)
@loader.command(
'ataskclear',
ru_doc='Очистить список задач.',
de_doc='Löschen Sie die Liste der Aufgaben.',
)
async def ataskclearcmd(self, m: Message):
"""Clear the list of tasks."""
self.set('tasks', {})
await utils.answer(m, self.strings('tasklistcleared'))
@loader.command(
'ataskpause',
ru_doc='Приостановить задачу.\nИспользование: .ataskpause <номер>\nБез аргументов — приостановить все задачи.',
de_doc='Aufgabe pausieren.\nVerwendung: .ataskpause \nOhne Argumente - alle Aufgaben pausieren.',
)
async def ataskpausecmd(self, m: Message):
"""Pause a task.
Usage: .ataskpause
If no arguments — pause all tasks."""
args = utils.get_args_raw(m)
if not args:
tasks = self.get('tasks')
for k, task in tasks.items():
task['paused'] = True
tasks[k] = task
self.set('tasks', tasks)
return await utils.answer(m, self.strings('taskpaused'))
try:
x = int(args)
except ValueError:
return await utils.answer(m, self.strings('args?!'))
x = str(x)
tasks = self.get('tasks')
if x not in tasks:
return await utils.answer(m, self.strings('tasknotfound'))
tasks[x]['paused'] = True
self.set('tasks', tasks)
await utils.answer(m, self.strings('taskpaused'))
@loader.command(
'ataskresume',
ru_doc='Возобновить задачу.\nИспользование: .ataskresume <номер>',
de_doc='Aufgabe fortsetzen.\nVerwendung: .ataskresume ',
)
async def ataskresumecmd(self, m: Message):
"""Resume a task.
Usage: .ataskresume """
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?!'))
try:
x = int(args)
except ValueError:
return await utils.answer(m, self.strings('args?!'))
tasks = self.get('tasks')
if x > len(tasks):
return await utils.answer(m, self.strings('tasknotfound'))
tasks[x - 1]['paused'] = False
self.set('tasks', tasks)
await utils.answer(m, self.strings('taskresumed'))
@loader.command(
'ataskexec',
ru_doc='Выполнить задачу сейчас и перепланировать согласно интервалу.\nИспользование: .ataskexec <номер>',
de_doc='Führen Sie die Aufgabe jetzt aus und planen Sie sie entsprechend dem Intervall neu.\nVerwendung: '
'.ataskexec ',
)
async def ataskexeccmd(self, m: Message):
"""Execute a task right now and replan according to the interval.
Usage: .ataskexec """
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?!'))
try:
x = int(args)
except ValueError:
return await utils.answer(m, self.strings('args?!'))
x = str(x)
tasks = self.get('tasks')
if x not in tasks:
return await utils.answer(m, self.strings('tasknotfound'))
task = tasks[x]
if task['paused']:
return await utils.answer(m, self.strings('taskpaused'))
task['next_execution'] = datetime.now() + self.convert_time(task['interval'])
self.set('tasks', tasks)
await utils.answer(
m, self.strings('taskpretimeexecuted').format(
at_time=datetime.strptime(task['next_execution'], '%d.%m.%Y %H:%M:%S') + timedelta(hours=self.get('tz'))
)
)
await self._run_task(task, x)
@loader.command(
'ataskreplan',
ru_doc='Изменить интервал задачи.\nИспользование: .ataskreplan <номер> <время>',
de_doc='Ändern Sie das Intervall der Aufgabe.\nVerwendung: .ataskreplan ',
)
async def ataskreplancmd(self, m: Message):
"""Change the interval of the task.
Usage: .ataskreplan """
args = utils.get_args_raw(m)
if not args:
return await utils.answer(m, self.strings('args?!'))
args = args.split(maxsplit=1)
x, time = args[0], args[1]
tasks = self.get('tasks')
if x not in tasks:
return await utils.answer(m, self.strings('tasknotfound'))
task = tasks[x]
if not self.validate_time(time):
return await utils.answer(m, self.strings('incorrecttime'))
task['interval'] = time
if task['paused']:
return await utils.answer(m, self.strings('taskpaused'))
task['next_execution'] = (datetime.now() + self.convert_time(task['interval'])).strftime('%d.%m.%Y %H:%M:%S')
tasks[x] = task
self.set('tasks', tasks)
await utils.answer(
m, self.strings('taskreplanned').format(
at_time=datetime.strptime(task['next_execution'], '%d.%m.%Y %H:%M:%S') + timedelta(hours=self.get('tz'))
)
)
@loader.command(
'adeftint',
ru_doc='Установить интервал по умолчанию.\nИспользование: .adeftint <время>',
de_doc='Setzen Sie das Standardintervall.\nVerwendung: .adeftint ',
)
async def adeftintcmd(self, m: Message):
"""Set the default interval.
Usage: .ataskdeftint