From 9b26946e067db1dce35efffdcc8c983c30f9a34c Mon Sep 17 00:00:00 2001 From: Beesquit Date: Mon, 15 Sep 2025 17:44:24 +0300 Subject: [PATCH] Updated structure and json work --- README.md | 15 ++++++++++ src/app/createApp.py | 9 ++++++ src/{ => app}/internal/internal.py | 0 src/{ => app}/jsonData/__init__.py | 4 +-- src/app/jsonData/connect.py | 47 ++++++++++++++++++++++++++++++ src/{ => app}/jsonData/utils.py | 8 ++--- src/{ => app}/settings.py | 5 ++-- src/app/telegram/__init__.py | 3 ++ src/{ => app}/telegram/strings.py | 0 src/{ => app}/telegram/telegram.py | 11 +++---- src/jsonData/connect.py | 39 ------------------------- src/main.py | 6 ++-- 12 files changed, 91 insertions(+), 56 deletions(-) create mode 100644 src/app/createApp.py rename src/{ => app}/internal/internal.py (100%) rename src/{ => app}/jsonData/__init__.py (53%) create mode 100644 src/app/jsonData/connect.py rename src/{ => app}/jsonData/utils.py (88%) rename src/{ => app}/settings.py (58%) create mode 100644 src/app/telegram/__init__.py rename src/{ => app}/telegram/strings.py (100%) rename src/{ => app}/telegram/telegram.py (94%) delete mode 100644 src/jsonData/connect.py diff --git a/README.md b/README.md index e69de29..c2d02e5 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,15 @@ +Project template for simple telegram bots + +Features: +- Base commands with FSM (no redis) +- JSON data storage +- Async worker function +- Cute project structure + +.env example: +```.env +botToken="token:from-botfather" +whitelist=["userid"] +dataPath="data/" +jsonFilename="data.json" +``` diff --git a/src/app/createApp.py b/src/app/createApp.py new file mode 100644 index 0000000..77ffca4 --- /dev/null +++ b/src/app/createApp.py @@ -0,0 +1,9 @@ +import asyncio + +from app.jsonData import start as start_json +from app.telegram import start_bot + + +def createApp(): + start_json() + asyncio.run(start_bot()) diff --git a/src/internal/internal.py b/src/app/internal/internal.py similarity index 100% rename from src/internal/internal.py rename to src/app/internal/internal.py diff --git a/src/jsonData/__init__.py b/src/app/jsonData/__init__.py similarity index 53% rename from src/jsonData/__init__.py rename to src/app/jsonData/__init__.py index 43405fc..cda2c47 100644 --- a/src/jsonData/__init__.py +++ b/src/app/jsonData/__init__.py @@ -1,5 +1,5 @@ -from connect import load, start -from utils import add, check, removeById, removeByParam +from .connect import load, start +from .utils import add, check, removeById, removeByParam __all__ = [ "load", diff --git a/src/app/jsonData/connect.py b/src/app/jsonData/connect.py new file mode 100644 index 0000000..0e4b8f5 --- /dev/null +++ b/src/app/jsonData/connect.py @@ -0,0 +1,47 @@ +import json +import os +import shutil +import sys +from datetime import datetime + +from loguru import logger + +from app.settings import settings + +dataPath = settings.dataPath.removesuffix("/") +jsonRawFilename = settings.jsonFilename.removesuffix(".json") +backupPath = dataPath + "/backup" +filePath = dataPath + "/" + jsonRawFilename + ".json" + + +def start(): + # Inits JSON file + try: + if not(os.path.exists(dataPath)): + os.mkdir(dataPath) + if not(os.path.exists(backupPath)): + os.mkdir(backupPath) + + if os.path.exists(filePath): + timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + backupFilePath = backupPath + "/" + jsonRawFilename + f"_backup_{timestamp}.json" + shutil.copy(filePath, backupFilePath) + logger.info(f"JSON backup was created: {backupFilePath}") + + with open(filePath, "w") as f: + json.dump({}, f, ensure_ascii = False, indent=4) + logger.success(f"Successfully initialized JSON with path: {filePath}") + except Exception as e: + logger.error(f"Failed to initialize JSON: {e}") + sys.exit(1) + + +def load(): + # Returnes the contents of the JSON file as a dictionary + data = {} + try: + with open(filePath, "r") as f: + data = json.load(f) + except json.decoder.JSONDecodeError: + logger.warning("JSON file is empty!") + return data diff --git a/src/jsonData/utils.py b/src/app/jsonData/utils.py similarity index 88% rename from src/jsonData/utils.py rename to src/app/jsonData/utils.py index 42a6ff8..754115d 100644 --- a/src/jsonData/utils.py +++ b/src/app/jsonData/utils.py @@ -1,9 +1,9 @@ import json -from connect import load from loguru import logger -from ..settings import settings +from app.jsonData.connect import load +from app.settings import settings def getParamId(param): @@ -34,7 +34,7 @@ def removeById(id: int): if id in currentData: del currentData[id] - with open(settings.jsonPath, 'w', encoding = 'utf-8') as f: + with open(settings.jsonFilename, 'w', encoding = 'utf-8') as f: json.dump(currentData, f, ensure_ascii = False, indent = 4) logger.info(f'Id {id} was deleted successfully!') return 0 @@ -62,7 +62,7 @@ def add(param): id = currentData[-1][0] + 1 newData = {id: param} - with open(settings.jsonPath, 'w', encoding = 'utf-8') as f: + with open(settings.jsonFilename, 'w', encoding = 'utf-8') as f: currentData.update(newData) json.dump(currentData, f, ensure_ascii = False, indent = 4) logger.info(f"Param {param} was added with id {id}") diff --git a/src/settings.py b/src/app/settings.py similarity index 58% rename from src/settings.py rename to src/app/settings.py index e3c66ab..49c66b2 100644 --- a/src/settings.py +++ b/src/app/settings.py @@ -5,9 +5,10 @@ class Settings(BaseSettings): botToken: str whitelist: list - jsonPath: str + dataPath: str + jsonFilename: str - modelConfig = SettingsConfigDict(env_file = ".env", env_file_encoding="utf-8") + model_config = SettingsConfigDict(env_file = ".env", env_file_encoding="utf-8") settings = Settings() # type: ignore diff --git a/src/app/telegram/__init__.py b/src/app/telegram/__init__.py new file mode 100644 index 0000000..8386961 --- /dev/null +++ b/src/app/telegram/__init__.py @@ -0,0 +1,3 @@ +from .telegram import start_bot + +__all__ = ["start_bot"] diff --git a/src/telegram/strings.py b/src/app/telegram/strings.py similarity index 100% rename from src/telegram/strings.py rename to src/app/telegram/strings.py diff --git a/src/telegram/telegram.py b/src/app/telegram/telegram.py similarity index 94% rename from src/telegram/telegram.py rename to src/app/telegram/telegram.py index 369c6bd..0df287b 100644 --- a/src/telegram/telegram.py +++ b/src/app/telegram/telegram.py @@ -1,6 +1,5 @@ import asyncio -import strings from aiogram import Bot, Dispatcher, F, Router from aiogram.client.default import DefaultBotProperties from aiogram.enums import ParseMode @@ -11,9 +10,10 @@ from aiogram.fsm.storage.memory import MemoryStorage from aiogram.types import BotCommand, BotCommandScopeDefault, Message from loguru import logger -import jsonData -from internal.internal import internal -from settings import settings +from app import jsonData +from app.internal.internal import internal +from app.settings import settings +from app.telegram import strings async def setCommands(): @@ -112,6 +112,7 @@ async def startBot(): await bot.send_message(chat_id=i, text=strings.startBot) except Exception as e: logger.error(e) + logger.success("Started bot") async def stopBot(): try: @@ -119,10 +120,10 @@ async def stopBot(): await bot.send_message(chat_id=i, text=strings.stopBot) except Exception as e: logger.error(e) + logger.success("Stopped bot") async def start_bot() -> None: - logger.info("Started bot!") dp.startup.register(startBot) dp.include_router(strategyRouter) dp.include_router(removeRouter) diff --git a/src/jsonData/connect.py b/src/jsonData/connect.py deleted file mode 100644 index b7ad657..0000000 --- a/src/jsonData/connect.py +++ /dev/null @@ -1,39 +0,0 @@ -import json -import os -import shutil -from datetime import datetime - -from loguru import logger - -from ..settings import settings - - -def start(): - # Inits JSON file - filePath = settings.jsonPath - - if not(os.path.exists('data')): - os.mkdir('data') - if not(os.path.exists('data/backup')): - os.mkdir('data/backup') - - if os.path.exists(filePath): - timestamp = datetime.now().strftime('%Y-%m-%d_%H-%M-%S') - backupPath = (f'data/backup/data_backup_{timestamp}.json') - shutil.copy(filePath, backupPath) - logger.info(f'JSON backup was created: {backupPath}') - - with open(filePath, 'w') as f: - json.dump({}, f, ensure_ascii = False, indent=4) - logger.info(f'New {filePath} created with empty JSON.') - - -def load(): - # Returnes the contents of the JSON file as a dictionary - data = {} - try: - with open(settings.jsonPath, 'r') as f: - data = json.load(f) - except json.decoder.JSONDecodeError: - logger.warning('JSON file is empty!') - return data diff --git a/src/main.py b/src/main.py index be5bb26..be05b51 100644 --- a/src/main.py +++ b/src/main.py @@ -1,5 +1,3 @@ -import asyncio +from app.createApp import createApp -from telegram.telegram import start_bot - -asyncio.run(start_bot()) +createApp()