commit 257b8ebb12d113b0670fa73c7f60ac7d65112910 Author: Beesquit Date: Fri Jul 18 14:42:11 2025 +0300 Initial commit diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cd5b5fe --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +#.dockerignore +# Docker +.dockerignore +dockerfile +compose.yaml +compose.yml + +# Git +.gitignore +*.md +example.env diff --git a/.env example b/.env example new file mode 100644 index 0000000..56f2847 --- /dev/null +++ b/.env example @@ -0,0 +1,2 @@ +BOT_TOKEN = "" +WHITELIST = "chatid1, chatid2" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5285038 --- /dev/null +++ b/.gitignore @@ -0,0 +1,85 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +env/ +venv/ +*.venv + +# Rope project settings +.ropeproject + +# mypy +.mypy_cache/ + +# VSCode +.vscode/ + +# JetBrains +.idea/ + +# .env +.env + +# test file +test.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..675524e --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# LIFE - LIFE is full ecosystem. +**Life-bot** - это бот связанный с `Telegram`. Он собирает статистику из разных сфер жизни. + +Конечная цель данной системы - получение информации с максимального числа сервисов через API, её обработка и отображение в удобном формате. Система должна работать по принципу *минимума усилий*. То есть заполнение информации должно быть максимально простым и комфортным, а в идеале потребность системы в нём должна отсутствовать. +### На момент 18.07.2025: + - В качестве платформы для отображения информации и доступа к файлам (не исходникам) внутри системы выбран `Obsidian` + - Для синхронизации с `Obsidian` выбран WebDAV протокол + - Бот поддерживает только одного пользователя diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..d3012cc --- /dev/null +++ b/compose.yml @@ -0,0 +1,11 @@ +services: + life-bot: + image: git.frik.su/eugenebee/life-bot:latest + container_name: life-bot + environment: + BOT_TOKEN: "telegram-bot-token" + WHITELIST: "chat-id-1, chat-id-2" + volumes: + - ./data:/app/data + - ./logs:/app/logs + restart: unless-stopped \ No newline at end of file diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/__main__.py b/src/__main__.py new file mode 100644 index 0000000..38f0f5f --- /dev/null +++ b/src/__main__.py @@ -0,0 +1,10 @@ +import asyncio + +from loguru import logger + +from telegram.controller import startup as telegramStartup + +if __name__ == "__main__": + logger.info("Starting python programm!") + asyncio.run(telegramStartup()) + logger.info("Python programm stopped!") diff --git a/src/config/credentials.py b/src/config/credentials.py new file mode 100644 index 0000000..3aaac53 --- /dev/null +++ b/src/config/credentials.py @@ -0,0 +1,6 @@ +from decouple import config + + +# Telegram + +bot_token = config('BOT_TOKEN', default='') diff --git a/src/config/options.py b/src/config/options.py new file mode 100644 index 0000000..07e6367 --- /dev/null +++ b/src/config/options.py @@ -0,0 +1,3 @@ +from decouple import config + +# todo diff --git a/src/config/strings.py b/src/config/strings.py new file mode 100644 index 0000000..5921341 --- /dev/null +++ b/src/config/strings.py @@ -0,0 +1,15 @@ +# Bot Statuses + +startBot = "Бот запущен!" + +stopBot = "Бот остановлен!" + +unexpectedError = "Возникла непредвиденная ошибка. :c" + +# Commands + +startCommand = "Привет! Я твой личный бот-трекер из системы LIFE." + +helpCommand = "Для описания финансов пишите +число или -число. " + +infoCommand = "Потрачено за сегодня:\nПолучено за сегодня:" diff --git a/src/config/whitelist.py b/src/config/whitelist.py new file mode 100644 index 0000000..f7afc2c --- /dev/null +++ b/src/config/whitelist.py @@ -0,0 +1,11 @@ +from decouple import config +import re + + +def checkWhiteList(id): + # Checks if id exists in the whitelist. Returnes 1 if exists and 0 if not + return id in chatIDs + + +chatIDsstring = config('WHITELIST', default='') +chatIDs = [int(x) for x in re.split(r',\s*', chatIDsstring)] diff --git a/src/telegram/controller.py b/src/telegram/controller.py new file mode 100644 index 0000000..8897208 --- /dev/null +++ b/src/telegram/controller.py @@ -0,0 +1,90 @@ +import asyncio + +from aiogram import Bot, Dispatcher +from aiogram.filters import Command +from aiogram.types import Message +from aiogram.client.default import DefaultBotProperties +from aiogram.enums import ParseMode +from aiogram.types import BotCommand, BotCommandScopeDefault + +from aiogram.fsm.context import FSMContext +from aiogram import Router, F +from aiogram.fsm.state import State, StatesGroup +from aiogram.fsm.storage.memory import MemoryStorage + +from loguru import logger + +from config import credentials, whitelist, options, strings + + +async def setCommands(): + commands = [BotCommand(command='start', description='Старт'), + BotCommand(command='help', description='Инструкция'), + BotCommand(command='info', description='Информация за день'), + ] + await bot.set_my_commands(commands, BotCommandScopeDefault()) + + +class startForm(StatesGroup): + pair = State() + params = State() + +class stopForm(StatesGroup): + pair = State() + + +dp = Dispatcher(storage=MemoryStorage()) +bot = Bot( + token=credentials.bot_token, + default=DefaultBotProperties(parse_mode=ParseMode.HTML), +) + +strategyRouter = Router() +stopRouter = Router() + + +@dp.message(Command("start")) +async def commandStart(message: Message) -> None: + await message.answer(strings.startCommand) + +@dp.message(Command("help"), F.chat.id.in_(whitelist.chatIDs)) +async def commandHelp(message: Message) -> None: + await message.answer(strings.helpCommand) + + +@dp.message(Command("info"), F.chat.id.in_(whitelist.chatIDs)) +async def commandInfo(message: Message) -> None: + msgText = strings.helpCommand + await message.answer(msgText) + + +@dp.message() +async def messageAny(message: Message) -> None: + await message.answer("you are a cat") + + +async def startBot(): + await setCommands() + try: + for i in whitelist.chatIDs: + await bot.send_message(chat_id=i, text=strings.startBot) + except Exception as e: + logger.error(f"Failed to start bot: {e}") + return + logger.success("Started bot!") + +async def stopBot(): + try: + for i in whitelist.chatIDs: + await bot.send_message(chat_id=i, text=strings.stopBot) + except Exception as e: + logger.error(f"Failed to stop bot: {e}") + return + logger.success("Stopped bot!") + +async def startup() -> None: + dp.include_router(strategyRouter) + dp.include_router(stopRouter) + dp.startup.register(startBot) + dp.shutdown.register(stopBot) + await dp.start_polling(bot) diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..e85ff67 --- /dev/null +++ b/todo.md @@ -0,0 +1,18 @@ +Версия 0.x.x +### ToFix + - [ ] Мяу + +### Новые функции + - [ ] Реализация взаимодействия с ботом через телеграмм + - - [ ] Реализация команд + - - - [x] Start + - - - [x] Help + - - - [ ] Info + - - [ ] Обработка других сообщений + - [ ] Реализация взаимодействия бота с WebDAV + - [ ] Конфигурация Obsidian + - [ ] Реализация развёртывания программы + - - [ ] Написать хорошую README.md + - - [ ] Написать compose.yml + - - [ ] Добавить requirements.txt + - - [ ] Добавить работу с gitea-runner