Обновление 2.0

This commit is contained in:
Profitroll 2021-04-24 03:08:43 +03:00
parent 310faaf79b
commit 2183db0515
8 changed files with 842 additions and 355 deletions

View File

@ -1,6 +1,5 @@
## Добро пожаловать в AutoZoom! ## Добро пожаловать в AutoZoom!
Contact me [directly](https://t.me/profitroll) or via [Support Center](https://www.tidio.com/talk/ydqcvfvgkud3jjk2482uaesvjpeohlh3) if you need English translation.
В этом файле описаны все шаги которые нужно выполнить для работы с программой. В этом файле описаны все шаги которые нужно выполнить для работы с программой.
### Содержание ### Содержание
@ -13,7 +12,6 @@ Contact me [directly](https://t.me/profitroll) or via [Support Center](https://w
* [GitHub вики проекта](https://github.com/profitrollgame/autozoom/wiki) * [GitHub вики проекта](https://github.com/profitrollgame/autozoom/wiki)
* [Обратная связь и предложения](https://t.me/profitroll) * [Обратная связь и предложения](https://t.me/profitroll)
* [Сообщить об ошибке/баге](https://github.com/profitrollgame/autozoom/issues) * [Сообщить об ошибке/баге](https://github.com/profitrollgame/autozoom/issues)
* [Центр поддержки](https://www.tidio.com/talk/ydqcvfvgkud3jjk2482uaesvjpeohlh3)
### 1. Информация и описание программы ### 1. Информация и описание программы

660
daemon.py

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +0,0 @@
{
"debug": false,
"shutdown_timeout": 30,
"shutdown_enabled": true,
"start": "shift+f7",
"stop": "shift+f8",
"telegram_enabled": false,
"use_colors": true,
"run_fullscreen": false,
"use_rpc": true,
"sounds": true,
"end_mode": "shutdown",
"obs_exe": null,
"obs_core": null
}

View File

@ -1,33 +1,130 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import pip import pip
import time
import json import json
import os import os
import shutil
import gzip
from datetime import datetime
from pathlib import Path from pathlib import Path
path = Path(__file__).resolve().parent path = Path(__file__).resolve().parent
sounds_folder = str(Path(str(path)+"/sounds/")) + os.sep sounds_folder = str(Path(str(path)+"/sounds/")) + os.sep
files_folder = str(Path(str(path)+"/files/")) + os.sep files_folder = str(Path(str(path)+"/files/")) + os.sep
logs_folder = str(Path(str(path)+"/logs/")) + os.sep
default_config = {
"debug": False,
"shutdown_timeout": 30,
"shutdown_enabled": True,
"start": "shift+f7",
"stop": "shift+f8",
"telegram_enabled": False,
"use_colors": True,
"run_fullscreen": False,
"use_rpc": True,
"sounds": True,
"end_mode": "shutdown",
"obs_exe": None,
"obs_core": None,
"update_check": True,
"write_logs": True,
"log_size": 512
}
# Функция проверки размера файла
def checkSize():
global logs_folder
i = 0
while i < 2:
try:
log = os.stat(logs_folder + 'latest.log')
if (log.st_size / 1024) > getConfig("log_size"):
with open(logs_folder + 'latest.log', 'rb') as f_in:
with gzip.open(f'{logs_folder}{datetime.now().strftime("%d.%m.%Y_%H:%M:%S")}.zip', 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
if getConfig("debug"):
print(f'Copied {logs_folder}{datetime.now().strftime("%d.%m.%Y_%H:%M:%S")}.zip')
open(logs_folder + 'latest.log', 'w').close()
i = 2
except FileNotFoundError:
if getConfig("debug"):
print('Log file not found')
time.sleep(2)
try:
log = open(logs_folder + 'latest.log', 'a')
open(logs_folder + 'latest.log', 'a').close()
except:
try:
os.mkdir(logs_folder)
log = open(logs_folder + 'latest.log', 'a')
open(logs_folder + 'latest.log', 'a').close()
except:
if getConfig("debug"):
time.sleep(2)
print('Log file could not be created')
i += 1
# Функция добавления в лог
def appendLog(message):
if getConfig("write_logs"):
global logs_folder
checkSize()
try:
log = open(logs_folder + 'latest.log', 'a')
open(logs_folder + 'latest.log', 'a').close()
except:
try:
os.mkdir(logs_folder)
log = open(logs_folder + 'latest.log', 'a')
open(logs_folder + 'latest.log', 'a').close()
except:
time.sleep(2)
print('Log file could not be created')
log.write(f'[{datetime.now().strftime("%H:%M:%S | %d.%m.%Y")}] {message}\n')
log.close()
# Функция добавления переменных, если их нет
def repairConfig(some_dic):
global files_folder
global default_config
for key in some_dic:
try:
some_dic[key]
except NameError:
some_dic[key] = default_config[key]
saveJson(files_folder+'config.json', some_dic)
def getConfig(some_var): def getConfig(some_var):
global files_folder global files_folder
global default_config
if os.path.exists(files_folder): if os.path.exists(files_folder):
if not os.path.exists(files_folder+'config.json'): if not os.path.exists(files_folder+'config.json'):
temp_config_list = {} temp_config_list = default_config
temp_config_list["debug"] = False
temp_config_list["shutdown_timeout"] = 30
temp_config_list["shutdown_enabled"] = True
temp_config_list["start"] = "shift+f7"
temp_config_list["stop"] = "shift+f8"
temp_config_list["telegram_enabled"] = False
temp_config_list["use_colors"] = True
temp_config_list["run_fullscreen"] = False
temp_config_list["use_rpc"] = True
temp_config_list["sounds"] = True
temp_config_list["end_mode"] = "shutdown"
temp_config_list["obs_exe"] = None
temp_config_list["obs_core"] = None
saveJson(files_folder+'config.json', temp_config_list) saveJson(files_folder+'config.json', temp_config_list)
return temp_config_list[some_var] return temp_config_list[some_var]
else: else:
@ -35,26 +132,24 @@ def getConfig(some_var):
with open(f"{files_folder}config.json", encoding="utf-8") as json_file: with open(f"{files_folder}config.json", encoding="utf-8") as json_file:
config_list = json.load(json_file) config_list = json.load(json_file)
json_file.close() json_file.close()
return config_list[some_var]
try:
return config_list[some_var]
except:
try:
repairConfig(config_list)
config_list = json.load(json_file)
json_file.close()
return config_list[some_var]
except:
return default_config[some_var]
except: except:
return "Error" return "Error"
else: else:
os.mkdir(files_folder) os.mkdir(files_folder)
if not os.path.exists(files_folder+'config.json'): if not os.path.exists(files_folder+'config.json'):
temp_config_list = {} temp_config_list = default_config
temp_config_list["debug"] = False
temp_config_list["shutdown_timeout"] = 30
temp_config_list["shutdown_enabled"] = True
temp_config_list["start"] = "shift+f7"
temp_config_list["stop"] = "shift+f8"
temp_config_list["telegram_enabled"] = False
temp_config_list["use_colors"] = True
temp_config_list["run_fullscreen"] = False
temp_config_list["use_rpc"] = True
temp_config_list["sounds"] = True
temp_config_list["end_mode"] = "shutdown"
temp_config_list["obs_exe"] = None
temp_config_list["obs_core"] = None
saveJson(files_folder+'config.json', temp_config_list) saveJson(files_folder+'config.json', temp_config_list)
return temp_config_list[some_var] return temp_config_list[some_var]
else: else:
@ -62,12 +157,22 @@ def getConfig(some_var):
with open(f"{files_folder}config.json", encoding="utf-8") as json_file: with open(f"{files_folder}config.json", encoding="utf-8") as json_file:
config_list = json.load(json_file) config_list = json.load(json_file)
json_file.close() json_file.close()
return config_list[some_var]
try:
return config_list[some_var]
except:
try:
repairConfig(config_list)
config_list = json.load(json_file)
json_file.close()
return config_list[some_var]
except:
return default_config[some_var]
except: except:
return "Error" return "Error"
def saveJson(filename, value): def saveJson(filename, value):
with open(filename, 'w', encoding="utf-8") as f: with open(filename, 'w', encoding="utf-8") as f:
json.dump(value, f, indent=4, ensure_ascii=False) json.dump(value, f, indent=4, ensure_ascii=False)

View File

@ -3,6 +3,7 @@
import os, sys import os, sys
from colors import * from colors import *
from functions import getConfig from functions import getConfig
from functions import appendLog
# Работает не очень стабильно при отсутствии интернета # Работает не очень стабильно при отсутствии интернета
# try: # try:
@ -24,65 +25,84 @@ libs = []
try: try:
import easygui import easygui
except ModuleNotFoundError: except ModuleNotFoundError:
appendLog("No module easygui")
libs.append("easygui") libs.append("easygui")
################################### ###################################
try: try:
import tkinter import tkinter
except ModuleNotFoundError: except ModuleNotFoundError:
appendLog("No module tkinter")
libs.append("tkinter") libs.append("tkinter")
################################### ###################################
try: try:
import keyboard import keyboard
except ModuleNotFoundError: except ModuleNotFoundError:
appendLog("No module keyboard")
libs.append("keyboard") libs.append("keyboard")
################################### ###################################
try: try:
import ast import ast
except ModuleNotFoundError: except ModuleNotFoundError:
appendLog("No module ast")
libs.append("ast") libs.append("ast")
################################### ###################################
try: try:
import inputimeout import inputimeout
except ModuleNotFoundError: except ModuleNotFoundError:
appendLog("No module inputimeout")
libs.append("inputimeout") libs.append("inputimeout")
################################### ###################################
try: try:
import telegram_send import telegram_send
except ModuleNotFoundError: except ModuleNotFoundError:
appendLog("No module telegram_send")
libs.append("telegram_send") libs.append("telegram_send")
################################### ###################################
try: try:
import wget import wget
except ModuleNotFoundError: except ModuleNotFoundError:
appendLog("No module wget")
libs.append("wget") libs.append("wget")
################################### ###################################
try: try:
import requests import requests
except ModuleNotFoundError: except ModuleNotFoundError:
appendLog("No module requests")
libs.append("requests") libs.append("requests")
################################### ###################################
try: try:
import playsound import playsound
except ModuleNotFoundError: except ModuleNotFoundError:
appendLog("No module playsound")
libs.append("playsound") libs.append("playsound")
################################### ###################################
try: try:
from zipfile import ZipFile from zipfile import ZipFile
except ModuleNotFoundError: except ModuleNotFoundError:
appendLog("No module zipfile")
libs.append("zipfile") libs.append("zipfile")
################################### ###################################
try: try:
import asyncio import asyncio
except ModuleNotFoundError: except ModuleNotFoundError:
appendLog("No module asyncio")
libs.append("asyncio") libs.append("asyncio")
################################### ###################################
try:
import getpass
except ModuleNotFoundError:
appendLog("No module getpass")
libs.append("getpass")
###################################
try: try:
from pypresence import Presence from pypresence import Presence
except ModuleNotFoundError: except ModuleNotFoundError:
appendLog("No module pypresence")
libs.append("pypresence") libs.append("pypresence")
################################### ###################################
if len(libs) > 0: if len(libs) > 0:
print("Не хватает нужных модулей, пробуем установить...") print("Не хватает нужных модулей, пробуем установить...\nЭто может занять некоторое время. Пожалуйста, не закрывайте программу.")
appendLog('Missing some modules, trying to install them')
for each in libs: for each in libs:
try: try:
@ -94,8 +114,14 @@ if len(libs) > 0:
response = os.system('"{}" -m pip install -U '.format(sys.executable) + each + " -q --no-warn-script-location") response = os.system('"{}" -m pip install -U '.format(sys.executable) + each + " -q --no-warn-script-location")
print(f"{RESET}[{BGREEN}OK{RESET}] Установлен модуль {YELLOW}{each}{RESET}.") print(f"{RESET}[{BGREEN}OK{RESET}] Установлен модуль {YELLOW}{each}{RESET}.")
appendLog(f'Module {each} installed')
if response != 0: if response != 0:
appendLog(f'Failed to install {each}')
sys.exit(f"{RESET}[{BRED}ERR{RESET}] Установка {YELLOW}{each} {RESET}провалилась.") sys.exit(f"{RESET}[{BRED}ERR{RESET}] Установка {YELLOW}{each} {RESET}провалилась.")
appendLog('Everything seems to be installed')
print(f"{RESET}[{BGREEN}OK{RESET}] Все модули были успешно установлены.") print(f"{RESET}[{BGREEN}OK{RESET}] Все модули были успешно установлены.")
try: try:
@ -109,6 +135,7 @@ if len(libs) > 0:
import requests import requests
import playsound import playsound
import asyncio import asyncio
import getpass
from zipfile import ZipFile from zipfile import ZipFile
from pypresence import Presence from pypresence import Presence
except ModuleNotFoundError: except ModuleNotFoundError:

144
main.py
View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys import sys
import pip
import webbrowser import webbrowser
import os import os
import time import time
@ -28,9 +29,10 @@ import libinstaller
import wget import wget
import requests import requests
import keyboard import keyboard
import getpass
from zipfile import ZipFile from zipfile import ZipFile
version = 1.8 version = 2.0
path = Path(__file__).resolve().parent path = Path(__file__).resolve().parent
def mainMenu(): def mainMenu():
@ -40,26 +42,38 @@ def mainMenu():
global version global version
global path global path
appendLog('Main menu opened')
rpc.inMenu() rpc.inMenu()
while True: while True:
print(f'{RESET}Загрузка данных о последней версии...') if getConfig("update_check"):
try: print(f'{RESET}Загрузка данных о последней версии...')
os.system("title Загрузка данных...")
serv_ver = requests.get("https://www.end-play.xyz/AutoZoomVersion.txt").text
os.system("title AutoZoom (Главная)")
clear()
except:
os.system("title Ошибка загрузки данных")
print(f'Не удалось загрузить данные о последней версии.\nПроверьте подключение к сети и повторите попытку.\n\nСтатус сервера центра обновлений:\n{BRED}https://status.end-play.xyz/786373747{RESET}')
none = input('\n > ')
rpc.disconnect()
sys.exit()
if float(serv_ver) > float(version):
show_version = f' ({BRED}!{RESET})'
else:
show_version = ''
try:
os.system("title Загрузка данных...")
serv_ver = requests.get("https://www.end-play.xyz/AutoZoomVersion.txt").text
os.system("title AutoZoom (Главная)")
clear()
except Exception as exp:
appendLog(f'Version number load failed {exp}')
os.system("title Ошибка загрузки данных")
print(f'Не удалось загрузить данные о последней версии.\nПроверьте подключение к сети и повторите попытку.\n\nСтатус сервера центра обновлений:\n{BRED}https://status.end-play.xyz/786373747{RESET}')
none = input('\n > ')
rpc.disconnect()
sys.exit()
if float(serv_ver) > float(version):
show_version = f' ({BRED}!{RESET})'
else:
show_version = ''
else:
os.system("title AutoZoom (Главная)")
show_version = ''
serv_ver = 'disabled'
appendLog('Skipping update check')
print(f'{BBLACK}»{RESET} Главное меню\n') print(f'{BBLACK}»{RESET} Главное меню\n')
print(f' {BRED}1.{RESET} Запуск') print(f' {BRED}1.{RESET} Запуск')
print(f' {BRED}2.{RESET} Редактор') print(f' {BRED}2.{RESET} Редактор')
@ -71,20 +85,26 @@ def mainMenu():
print(RESET) print(RESET)
if menu_choose == '1': if menu_choose == '1':
appendLog('Went to daemon')
main('menu') main('menu')
elif menu_choose == '2': elif menu_choose == '2':
appendLog('Went to editor')
rpc.inEditor() rpc.inEditor()
editor() editor()
elif menu_choose == '3': elif menu_choose == '3':
appendLog('Went to settings')
rpc.inSettings() rpc.inSettings()
settings() settings()
elif menu_choose == '4': elif menu_choose == '4':
appendLog('Went to updater')
rpc.inUpdater() rpc.inUpdater()
updater(serv_ver, version) updater(serv_ver, version)
elif menu_choose == '5': elif menu_choose == '5':
appendLog('Went to help')
rpc.inHelp() rpc.inHelp()
helpMenu() helpMenu()
elif menu_choose == '6': elif menu_choose == '6':
appendLog('Exited AutoZoom')
rpc.disconnect() rpc.disconnect()
clear() clear()
sys.exit() sys.exit()
@ -109,44 +129,74 @@ def helpMenu():
try: try:
while True: while True:
os.system("title AutoZoom (Помощь)") os.system("title AutoZoom (Помощь)")
appendLog('Help menu opened')
clear() clear()
global version global version
global path global path
print(f'{BBLACK}»{RESET} Меню помощи\n') print(f'{BBLACK}»{RESET} Меню помощи\n')
print(f' {BRED}1.{RESET} Документация') print(f' {BRED}1.{RESET} Документация')
print(f' {BRED}2.{RESET} Telegram проекта') print(f' {BRED}2.{RESET} Сайт проекта')
print(f' {BRED}3.{RESET} Связаться с автором') print(f' {BRED}3.{RESET} Центр поддержки')
print(f' {BRED}4.{RESET} Сводка информации') print(f' {BRED}4.{RESET} Telegram проекта')
print(f' {BRED}5.{RESET} В главное меню') print(f' {BRED}5.{RESET} Связаться с автором')
print(f' {BRED}6.{RESET} Сводка информации')
print(f' {BRED}7.{RESET} В главное меню')
help_choose = input(f'\n > {BRED}') help_choose = input(f'\n > {BRED}')
if help_choose == '1': if help_choose == '1':
try: try:
clear() clear()
appendLog('Opened AutoZoom wiki')
webbrowser.open("https://github.com/profitrollgame/autozoom/wiki") webbrowser.open("https://github.com/profitrollgame/autozoom/wiki")
except: except Exception as exp:
clear() clear()
appendLog(f'Failed to open AutoZoom wiki: {exp}')
none = input(f'{RESET}Не удалось открыть страницу вашего браузера.\nВы можете открыть адрес самостоятельно: {BRED}https://github.com/profitrollgame/autozoom/wiki{RESET}\n\n > ') none = input(f'{RESET}Не удалось открыть страницу вашего браузера.\nВы можете открыть адрес самостоятельно: {BRED}https://github.com/profitrollgame/autozoom/wiki{RESET}\n\n > ')
clear() clear()
elif help_choose == '2': elif help_choose == '2':
try: try:
clear() clear()
webbrowser.open("https://t.me/auto_zoom") appendLog('Opened AutoZoom website')
except: webbrowser.open("https://www.end-play.xyz/autozoom")
except Exception as exp:
clear() clear()
none = input(f'{RESET}Не удалось открыть страницу вашего браузера.\nВы можете открыть адрес самостоятельно: {BRED}https://t.me/auto_zoom{RESET}\n\n > ') appendLog(f'Failed to open AutoZoom website: {exp}')
none = input(f'{RESET}Не удалось открыть страницу вашего браузера.\nВы можете открыть адрес самостоятельно: {BRED}https://www.end-play.xyz/autozoom{RESET}\n\n > ')
clear() clear()
elif help_choose == '3': elif help_choose == '3':
try: try:
clear() clear()
webbrowser.open("https://t.me/profitroll") appendLog('Opened AutoZoom support center')
except: webbrowser.open("https://www.tidio.com/talk/ydqcvfvgkud3jjk2482uaesvjpeohlh3")
except Exception as exp:
clear() clear()
appendLog(f'Failed to open AutoZoom support center: {exp}')
none = input(f'{RESET}Не удалось открыть страницу вашего браузера.\nВы можете открыть адрес самостоятельно: {BRED}https://www.tidio.com/talk/ydqcvfvgkud3jjk2482uaesvjpeohlh3{RESET}\n\n > ')
clear()
elif help_choose == '4':
try:
clear()
appendLog('Opened AutoZoom Telegram group')
webbrowser.open("https://t.me/auto_zoom")
except Exception as exp:
clear()
appendLog(f'Failed to open AutoZoom Telegram group: {exp}')
none = input(f'{RESET}Не удалось открыть страницу вашего браузера.\nВы можете открыть адрес самостоятельно: {BRED}https://t.me/auto_zoom{RESET}\n\n > ')
clear()
elif help_choose == '5':
try:
clear()
appendLog('Opened AutoZoom\'s developer Telegram')
webbrowser.open("https://t.me/profitroll")
except Exception as exp:
clear()
appendLog(f'Failed to open AutoZoom\'s developer Telegram: {exp}')
none = input(f'{RESET}Не удалось открыть страницу вашего браузера.\nВы можете открыть адрес самостоятельно: {BRED}https://t.me/profitroll{RESET}\n\n > ') none = input(f'{RESET}Не удалось открыть страницу вашего браузера.\nВы можете открыть адрес самостоятельно: {BRED}https://t.me/profitroll{RESET}\n\n > ')
clear() clear()
if help_choose == '4': if help_choose == '6':
clear() clear()
appendLog(f'Showing system information:\n=============================================\nHelpful data for fault search:\n\nOS: {platform.system()}\nRelease: {platform.release()}\nArch: {os_arch()}\nPy Ver: {platform.python_version()}\nPIP Ver: {pip.__version__}\nImpl: {platform.python_implementation()}\nRev: {platform.python_revision()}\nPy Path: {sys.path[4]}\nAZ Ver: {version}\nAZ User: {getpass.getuser()}\nAZ Path: {path}\n=============================================')
print(f'{BBLACK}»{RESET} Информация о системе\n') print(f'{BBLACK}»{RESET} Информация о системе\n')
print(' Система:') print(' Система:')
print(f' {BBLACK}{RESET} ОС: {YELLOW}{platform.system()}{RESET}') print(f' {BBLACK}{RESET} ОС: {YELLOW}{platform.system()}{RESET}')
@ -154,15 +204,17 @@ def helpMenu():
print(f' {BBLACK}{RESET} Разрядность: {YELLOW}{os_arch()}{RESET}') print(f' {BBLACK}{RESET} Разрядность: {YELLOW}{os_arch()}{RESET}')
print('\n Python:') print('\n Python:')
print(f' {BBLACK}{RESET} Версия: {YELLOW}{platform.python_version()}{RESET}') print(f' {BBLACK}{RESET} Версия: {YELLOW}{platform.python_version()}{RESET}')
print(f' {BBLACK}{RESET} Версия PIP: {YELLOW}{pip.__version__}{RESET}')
print(f' {BBLACK}{RESET} Вариант: {YELLOW}{platform.python_implementation()}{RESET}') print(f' {BBLACK}{RESET} Вариант: {YELLOW}{platform.python_implementation()}{RESET}')
print(f' {BBLACK}{RESET} Ревизия: {YELLOW}{platform.python_revision()}{RESET}') print(f' {BBLACK}{RESET} Ревизия: {YELLOW}{platform.python_revision()}{RESET}')
print(f' {BBLACK}{RESET} Расположение: {BRED}{sys.path[4]}{RESET}') print(f' {BBLACK}{RESET} Расположение: {BRED}{sys.path[4]}{RESET}')
print('\n AutoZoom:') print('\n AutoZoom:')
print(f' {BBLACK}{RESET} Версия: {YELLOW}{version}{RESET}') print(f' {BBLACK}{RESET} Версия: {YELLOW}{version}{RESET}')
print(f' {BBLACK}{RESET} Пользователь: {YELLOW}{getpass.getuser()}{RESET}')
print(f' {BBLACK}{RESET} Расположение: {BRED}{path}{RESET}') print(f' {BBLACK}{RESET} Расположение: {BRED}{path}{RESET}')
none = input('\n > ') none = input('\n > ')
clear() clear()
elif help_choose == '5': elif help_choose == '7':
rpc.inMenu() rpc.inMenu()
clear() clear()
os.system("title AutoZoom (Главная)") os.system("title AutoZoom (Главная)")
@ -179,13 +231,20 @@ def updater(serv_ver, version):
try: try:
while True: while True:
os.system("title AutoZoom (Обновления)") os.system("title AutoZoom (Обновления)")
appendLog('Updater menu opened')
clear() clear()
if float(serv_ver) > float(version): if float(serv_ver) > float(version):
show_version = f' ({BRED}!{RESET})' show_version = f' ({BRED}!{RESET})'
serv_ver = serv_ver.rstrip('\n') serv_ver = serv_ver.rstrip('\n')
show_action = f'Обновить до {BGREEN}{serv_ver}{RESET}' show_action = f'Обновить до {BGREEN}{serv_ver}{RESET}'
changelog_text = f'Изменения в версии {BGREEN}{serv_ver}{RESET}:' changelog_text = f'Изменения в версии {BGREEN}{serv_ver}{RESET}:'
changelog_footer = '\nОбновитесь чтобы вышеуказанное работало.' changelog_footer = '\nОбновитесь чтобы вышеуказанное работало.'
elif serv_ver == 'disabled':
show_version = ''
show_action = f'Переустановить'
changelog_text = f'Изменения в вашей версии:'
changelog_footer = ''
else: else:
show_version = '' show_version = ''
show_action = f'Переустановить' show_action = f'Переустановить'
@ -198,7 +257,10 @@ def updater(serv_ver, version):
print(f' {BRED}2.{RESET} Список изменений') print(f' {BRED}2.{RESET} Список изменений')
print(f' {BRED}3.{RESET} В главное меню') print(f' {BRED}3.{RESET} В главное меню')
updater_choose = input(f'\n > {BRED}') updater_choose = input(f'\n > {BRED}')
if updater_choose == '1': if updater_choose == '1':
appendLog('Choosed to update')
while True: while True:
clear() clear()
print(f'{RESET}Подтвердите действие:\n') print(f'{RESET}Подтвердите действие:\n')
@ -207,54 +269,69 @@ def updater(serv_ver, version):
updater_decide = input('\n > ') updater_decide = input('\n > ')
if updater_decide == '1': if updater_decide == '1':
appendLog('Trying to update AutoZoom')
clear() clear()
try: try:
wget.download('https://www.end-play.xyz/AutoZoomLatest.zip', out='AutoZoomLatest.zip') wget.download('https://www.end-play.xyz/AutoZoomLatest.zip', out='AutoZoomLatest.zip')
except: appendLog('Latest zip downloaded')
except Exception as exp:
print(f'Не удалось загрузить архив с последней версией.\nПроверьте подключение к сети и повторите попытку.\n\nСтатус сервера центра обновлений:\n{BRED}https://status.end-play.xyz/786373747{RESET}') print(f'Не удалось загрузить архив с последней версией.\nПроверьте подключение к сети и повторите попытку.\n\nСтатус сервера центра обновлений:\n{BRED}https://status.end-play.xyz/786373747{RESET}')
appendLog(f'Failed to download zip: {exp}')
none = input('\n > ') none = input('\n > ')
continue continue
with ZipFile('AutoZoomLatest.zip', 'r') as zipObj: with ZipFile('AutoZoomLatest.zip', 'r') as zipObj:
zipObj.extractall() zipObj.extractall()
print('Все файлы были успешно загружены') print('Все файлы были успешно загружены')
appendLog('Latest zip extracted')
if os.path.exists("AutoZoomLatest.zip"): if os.path.exists("AutoZoomLatest.zip"):
os.remove("AutoZoomLatest.zip") os.remove("AutoZoomLatest.zip")
appendLog('Latest used zip deleted')
clear() clear()
none = input('Обновление завершено, перезапустите AutoZoom.\n\n > ') none = input('Обновление завершено, перезапустите AutoZoom.\n\n > ')
rpc.disconnect() rpc.disconnect()
clear() clear()
print(f'Закрываем приложение {BGREEN}AutoZoom{RESET}...') print(f'Закрываем приложение {BGREEN}AutoZoom{RESET}...')
appendLog('Exiting AutoZoom after an update')
sys.exit() sys.exit()
elif updater_decide == '2': elif updater_decide == '2':
clear() clear()
appendLog('Aborted update')
break break
else: else:
continue continue
elif updater_choose == '2': elif updater_choose == '2':
appendLog('Choosed to check changelog')
try: try:
changelog = requests.get("https://www.end-play.xyz/AutoZoomChangelog.txt") changelog = requests.get("https://www.end-play.xyz/AutoZoomChangelog.txt")
changelog.encoding = None changelog.encoding = None
appendLog('Changelog loaded')
clear() clear()
print(f'{RESET}{changelog_text}\n') print(f'{RESET}{changelog_text}\n')
print(changelog.text) print(changelog.text)
print(changelog_footer) print(changelog_footer)
none = input('\n > ') none = input('\n > ')
continue continue
except: except Exception as exp:
print(f'{RESET}Не удалось загрузить чейнджлог.\nПроверьте подключение к сети и повторите попытку.\n\nСтатус сервера центра обновлений:\n{BRED}https://status.end-play.xyz/786373747{RESET}') print(f'{RESET}Не удалось загрузить чейнджлог.\nПроверьте подключение к сети и повторите попытку.\n\nСтатус сервера центра обновлений:\n{BRED}https://status.end-play.xyz/786373747{RESET}')
appendLog(f'Failed to check changelog: {exp}')
none = input('\n > ') none = input('\n > ')
continue continue
elif updater_choose == '3': elif updater_choose == '3':
rpc.inMenu() rpc.inMenu()
clear() clear()
appendLog('Returning to main menu')
os.system("title AutoZoom (Главная)") os.system("title AutoZoom (Главная)")
return return
else: else:
continue continue
except KeyboardInterrupt: except KeyboardInterrupt:
rpc.inMenu() rpc.inMenu()
clear() clear()
@ -271,6 +348,7 @@ if __name__ == '__main__':
keyboard.press('alt, enter') keyboard.press('alt, enter')
time.sleep(.25) time.sleep(.25)
keyboard.release('alt, enter') keyboard.release('alt, enter')
os.system("title AutoZoom (Главная)") os.system("title AutoZoom (Главная)")
mainMenu() mainMenu()
sys.exit() sys.exit()

12
requirements.txt Normal file
View File

@ -0,0 +1,12 @@
easygui
tkinter
keyboard
ast
inputimeout
telegram_send
wget
requests
playsound
asyncio
zipfile
pypresence

168
rpc.py
View File

@ -6,7 +6,7 @@ import sys
from colors import * from colors import *
from functions import * from functions import *
version = '1.8' version = '2.0'
import libinstaller import libinstaller
from pypresence import Presence from pypresence import Presence
@ -33,8 +33,9 @@ def disconnect():
try: try:
RPC.close() RPC.close()
connected = False connected = False
appendLog('Discord RPC disconnected')
except: except:
pass appendLog('Discord RPC failed to disconnect')
def connect(): def connect():
global connected global connected
@ -42,12 +43,14 @@ def connect():
try: try:
RPC.connect() RPC.connect()
connected = True connected = True
appendLog('Discord RPC connected')
except: except:
pass appendLog('Discord RPC failed to connect')
def reset(): def reset():
if getConfig("use_rpc"): if getConfig("use_rpc"):
RPC.clear() RPC.clear()
appendLog('Discord RPC status cleared')
@ -56,12 +59,15 @@ def waitLesson(lesson, start):
if getConfig("use_rpc"): if getConfig("use_rpc"):
if connected == False: if connected == False:
connect() connect()
RPC.update(large_image='1024_cover', small_image='status_waiting', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Ожидание', state=f'Ждём начала «{lesson}»', details='Урок не начался', start=start) RPC.update(large_image='1024_cover', small_image='status_waiting', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Ожидание', state=f'Ждём начала «{lesson}»', details='Конференция не началась', start=start)
appendLog(f'Discord RPC changed to waitLesson (Lesson: {lesson}, Start: {start})')
except AttributeError: except AttributeError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
except AssertionError: except AssertionError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
@ -71,12 +77,15 @@ def onLesson(lesson, start):
if getConfig("use_rpc"): if getConfig("use_rpc"):
if connected == False: if connected == False:
connect() connect()
RPC.update(large_image='1024_cover', small_image='status_lesson', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Урок', state=f'Слушаем «{lesson}»', details='Идёт урок', start=start) RPC.update(large_image='1024_cover', small_image='status_lesson', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Конференция', state=f'Слушаем «{lesson}»', details='Идёт конференция', start=start)
appendLog(f'Discord RPC changed to onLesson (Lesson: {lesson}, Start: {start})')
except AttributeError: except AttributeError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
except AssertionError: except AssertionError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
@ -87,11 +96,14 @@ def inMenu():
if connected == False: if connected == False:
connect() connect()
RPC.update(large_image='1024_cover', small_image='status_menu', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Главное меню', state='Открыт список опций', details='В главном меню') RPC.update(large_image='1024_cover', small_image='status_menu', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Главное меню', state='Открыт список опций', details='В главном меню')
appendLog('Discord RPC changed to inMenu')
except AttributeError: except AttributeError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
except AssertionError: except AssertionError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
@ -102,11 +114,14 @@ def shutdown(end):
if connected == False: if connected == False:
connect() connect()
RPC.update(large_image='1024_cover', small_image='status_shutdown', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Выключение', state='Отсчёт до авто-выключения', details='Выключение ПК', end=end) RPC.update(large_image='1024_cover', small_image='status_shutdown', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Выключение', state='Отсчёт до авто-выключения', details='Выключение ПК', end=end)
appendLog(f'Discord RPC changed to shutdown (End: {end})')
except AttributeError: except AttributeError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
except AssertionError: except AssertionError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
@ -117,11 +132,14 @@ def inSettings():
if connected == False: if connected == False:
connect() connect()
RPC.update(large_image='1024_cover', small_image='status_settings', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Настройки', state='Открыты настройки', details='В главном меню') RPC.update(large_image='1024_cover', small_image='status_settings', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Настройки', state='Открыты настройки', details='В главном меню')
appendLog('Discord RPC changed to inSettings')
except AttributeError: except AttributeError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
except AssertionError: except AssertionError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
@ -132,11 +150,14 @@ def inEditor():
if connected == False: if connected == False:
connect() connect()
RPC.update(large_image='1024_cover', small_image='status_editing', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Редактор', state='Открыт редактор', details='В главном меню') RPC.update(large_image='1024_cover', small_image='status_editing', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Редактор', state='Открыт редактор', details='В главном меню')
appendLog('Discord RPC changed to inEditor')
except AttributeError: except AttributeError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
except AssertionError: except AssertionError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
@ -147,11 +168,14 @@ def inUpdater():
if connected == False: if connected == False:
connect() connect()
RPC.update(large_image='1024_cover', small_image='status_updating', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Обновление', state='Открыт центр обновлений', details='В главном меню') RPC.update(large_image='1024_cover', small_image='status_updating', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Обновление', state='Открыт центр обновлений', details='В главном меню')
appendLog('Discord RPC changed to inUpdater')
except AttributeError: except AttributeError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
except AssertionError: except AssertionError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
@ -162,134 +186,44 @@ def inHelp():
if connected == False: if connected == False:
connect() connect()
RPC.update(large_image='1024_cover', small_image='status_support', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Помощь', state='Открыта помощь', details='В главном меню') RPC.update(large_image='1024_cover', small_image='status_support', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Помощь', state='Открыта помощь', details='В главном меню')
appendLog('Discord RPC changed to inHelp')
except AttributeError: except AttributeError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
except AssertionError: except AssertionError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
def lessonEnded():
try:
if getConfig("use_rpc"):
if connected == False:
connect()
RPC.update(large_image='1024_cover', small_image='status_waiting', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Ожидание', state=f'Ждём указаний', details='Все конференции закончились')
appendLog('Discord RPC changed to lessonEnded')
except AttributeError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1)
except AssertionError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1)
if __name__ == "__main__": if __name__ == "__main__":
try: try:
RPC.connect() RPC.connect()
RPC.update(large_image='1024_cover', small_image='status_settings', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Отладка', state='Модуль Discord RPC запущен в режиме тестирования', details='Режим отладки') RPC.update(large_image='1024_cover', small_image='status_settings', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Отладка', state='Модуль Discord RPC запущен в режиме тестирования', details='Режим отладки')
appendLog('Discord RPC changed to debug')
except AttributeError: except AttributeError:
appendLog('Discord RPC failed to change status')
if getConfig("debug"): if getConfig("debug"):
print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.') print(f'{RESET}Модуль {BRED}Discord RPC {RESET}не смог подключиться.\nВозможно, ваш {CYAN}Discord {RESET}не открыт.')
time.sleep(1) time.sleep(1)
################################################################################
# Неудачная попытка работы с discord_rpc. Потом, быть может, попробую ещё раз. #
################################################################################
# import discord_rpc
# import time
# if __name__ == "__main__":
# def readyCallback(current_user):
# print('Our user: {}'.format(current_user))
# def disconnectedCallback(codeno, codemsg):
# print('Disconnected from Discord rich presence RPC. Code {}: {}'.format(
# codeno, codemsg
# ))
# def errorCallback(errno, errmsg):
# print('An error occurred! Error {}: {}'.format(
# errno, errmsg
# ))
# # Note: 'event_name': callback
# callbacks = {
# 'ready': readyCallback,
# 'disconnected': disconnectedCallback,
# 'error': errorCallback,
# }
# # if __name__ != "__main__":
# discord_rpc.initialize('800049969960058882', callbacks=callbacks, log=False)
# none = input('init')
# i = 0
# while i < 10:
# discord_rpc.update_presence(
# **{
# 'state': f'Загрузка...',
# 'details': 'Загрузка...',
# #'start_timestamp': start,
# 'large_image_key': '1024_cover',
# 'small_image_key': 'status_waiting',
# 'large_image_text': f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom',
# 'small_image_text': 'Ожидание',
# }
# )
# discord_rpc.update_connection()
# time.sleep(3)
# discord_rpc.run_callbacks()
# i += 1
# i = 0
# start = time.time()
# while i < 10:
# i += 1
#large_image='1024_cover', small_image='status_waiting', large_text=f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom', small_text='Ожидание', state=f'Ждём начала «{lesson}»', details='Урок не начался', start=start
# discord_rpc.update_presence(
# **{
# 'state': f'Ждём начала «lesson»',
# 'details': 'Урок не начался',
# 'start_timestamp': start,
# 'large_image_key': '1024_cover',
# 'small_image_key': 'status_waiting',
# 'large_image_text': f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom',
# 'small_image_text': 'Ожидание',
# }
# )
# discord_rpc.update_connection()
# time.sleep(1)
# discord_rpc.run_callbacks()
# discord_rpc.shutdown()
# def disconnect():
# if getConfig("use_rpc"):
# discord_rpc.shutdown()
# def inMenu():
# if getConfig("use_rpc"):
# discord_rpc.update_presence(
# **{
# 'state': f'Ждём начала «lesson»',
# 'details': 'Урок не начался',
# #'start_timestamp': start,
# 'large_image_key': '1024_cover',
# 'small_image_key': 'status_waiting',
# 'large_image_text': f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom',
# 'small_image_text': 'Ожидание',
# }
# )
# discord_rpc.update_connection()
# def waitLesson(lesson, start):
# if getConfig("use_rpc"):
# discord_rpc.update_presence(
# **{
# 'state': f'Ждём начала «lesson»',
# 'details': 'Урок не начался',
# 'start_timestamp': start,
# 'large_image_key': '1024_cover',
# 'small_image_key': 'status_waiting',
# 'large_image_text': f'AutoZoom • v{version}\nhttp://bit.ly/auto_zoom',
# 'small_image_text': 'Ожидание',
# }
# )