diff --git a/heroku/modules/loader.py b/heroku/modules/loader.py index d7ca87c..0f27eec 100644 --- a/heroku/modules/loader.py +++ b/heroku/modules/loader.py @@ -1347,9 +1347,9 @@ class LoaderMod(loader.Module): file.name = f"{class_name}.py" file.seek(0) - await utils.answer_file( + await utils.answer( message, - file, + file=file, caption=text, reply_to=getattr(message, "reply_to_msg_id", None), ) diff --git a/heroku/modules/updater.py b/heroku/modules/updater.py index 61c7a3b..d6b987f 100644 --- a/heroku/modules/updater.py +++ b/heroku/modules/updater.py @@ -15,6 +15,7 @@ import asyncio import contextlib import logging import os +import requests import subprocess import sys import time @@ -31,7 +32,7 @@ from herokutl.tl.types import DialogFilter, Message from .. import loader, main, utils, version from .._internal import restart -from ..inline.types import InlineCall +from ..inline.types import InlineCall, BotInlineCall logger = logging.getLogger(__name__) @@ -55,9 +56,26 @@ class UpdaterMod(loader.Module): "disable_notifications", doc=lambda: self.strings("_cfg_doc_disable_notifications"), validator=loader.validators.Boolean(), - ) + ), + loader.ConfigValue( + "autoupdate", + doc=lambda: self.strings("_cfg_doc_autoupdate"), + validator=loader.validators.Boolean(), + ), ) + async def _set_autoupdate_state(self, call: BotInlineCall, state: bool): + if not state: + self.config["autoupdate"] = False + await self.inline.bot(call.answer(self.strings("autoupdate_off").format(prefix=self.get_prefix()), show_alert=True)) # "Автоматическое обновление выключено. Используйте {prefix}(команда), чтобы включить его." + await call.delete() + return + + self.config["autoupdate"] = True + + await self.inline.bot(call.answer(self.strings("autoupdate_on").format(prefix=self.get_prefix()), show_alert=True)) + await call.delete() + def get_changelog(self) -> str: try: repo = git.Repo() @@ -93,7 +111,7 @@ class UpdaterMod(loader.Module): @loader.loop(interval=60, autostart=True) async def poller(self): - if self.config["disable_notifications"] or not self.get_changelog(): + if (self.config["disable_notifications"] and not self.config["autoupdate"]) or not self.get_changelog(): return self._pending = self.get_latest() @@ -106,27 +124,62 @@ class UpdaterMod(loader.Module): return if self._pending not in {utils.get_git_hash(), self._notified}: - m = await self.inline.bot.send_photo( - self.tg_id, - "https://raw.githubusercontent.com/coddrago/assets/refs/heads/main/heroku/updated.png", - caption=self.strings("update_required").format( - utils.get_git_hash()[:6], - '{}'.format( - utils.get_git_hash()[:12], - self.get_latest()[:12], - self.get_latest()[:6], + if not self.config["autoupdate"]: manual_update = True + else: + try: + ver = f"https://api.github.com/repos/coddrago/Heroku/contents/heroku/version.py?ref={version.branch}" + text = requests.get(ver, headers={"Accept": "application/vnd.github.v3.raw"}).text + new_version = "" + for line in text.splitlines(): + if line.strip().startswith("__version__"): + new_version = line.split("=", 1)[1] .strip(" ()") .split(",")[0] + + if (str(version.__version__[0]) == new_version): + manual_update = False + else: + logger.info("Got a major update, updating manually") + manual_update = True + except: + manual_update = False + + if manual_update: + m = await self.inline.bot.send_photo( + self.tg_id, + "https://raw.githubusercontent.com/coddrago/assets/refs/heads/main/heroku/updated.png", + caption=self.strings("update_required").format( + utils.get_git_hash()[:6], + '{}'.format( + utils.get_git_hash()[:12], + self.get_latest()[:12], + self.get_latest()[:6], + ), + self.get_changelog(), ), - self.get_changelog(), - ), - reply_markup=self._markup(), - ) + reply_markup=self._markup(), + ) - self._notified = self._pending - self.set("ignore_permanent", False) + self._notified = self._pending + self.set("ignore_permanent", False) - await self._delete_all_upd_messages() + await self._delete_all_upd_messages() - self.set("upd_msg", m.message_id) + self.set("upd_msg", m.message_id) + + else: + m = await self.inline.bot.send_photo( + self.tg_id, + "https://raw.githubusercontent.com/coddrago/assets/refs/heads/main/heroku/updated.png", + caption=self.strings("autoupdate_notification").format( + utils.get_git_hash()[:6], + '{}'.format( + utils.get_git_hash()[:12], + self.get_latest()[:12], + self.get_latest()[:6], + ), + self.get_changelog(), + ), + ) + await self.invoke("update", "-f", peer=self.inline.bot_username) async def _delete_all_upd_messages(self): for client in self.allclients: @@ -303,6 +356,8 @@ class UpdaterMod(loader.Module): except subprocess.CalledProcessError: logger.exception("Req install failed") + async def autoupdate(self): pass + @loader.command() async def update(self, message: Message): try: @@ -419,6 +474,31 @@ class UpdaterMod(loader.Module): self.set("do_not_create", True) + if not isinstance(self.config["autoupdate"], bool): + await self.inline.bot.send_photo( + self.tg_id, + photo="https://raw.githubusercontent.com/coddrago/assets/refs/heads/main/heroku/unit_alpha.png", + caption=self.strings("autoupdate"), # "⌚️ Юнит «ALPHA» автоматически обновляет юзербота сразу после выхода нового патча. Только мажорные обновления (1.x.x > 2.x.x) будут требовать вашего внимания\n\n🔄 Не хотите ли включить автообновление?" + reply_markup=self.inline.generate_markup( + [ + [ + { + "text": f"✅ Turn on", + "callback": self._set_autoupdate_state, + "args": (True,), + } + ], + [ + { + "text": "🚫 Turn off", + "callback": self._set_autoupdate_state, + "args": (False,), + } + ] + ] + ), + ) + async def _add_folder(self): folders = await self._client(GetDialogFiltersRequest())