Initial commit
This commit is contained in:
11
.dockerignore
Normal file
11
.dockerignore
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#.dockerignore
|
||||||
|
# Docker
|
||||||
|
.dockerignore
|
||||||
|
dockerfile
|
||||||
|
compose.yaml
|
||||||
|
compose.yml
|
||||||
|
|
||||||
|
# Git
|
||||||
|
.gitignore
|
||||||
|
*.md
|
||||||
|
example.env
|
||||||
2
.env example
Normal file
2
.env example
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
BOT_TOKEN = ""
|
||||||
|
WHITELIST = "chatid1, chatid2"
|
||||||
85
.gitignore
vendored
Normal file
85
.gitignore
vendored
Normal file
@ -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
|
||||||
8
README.md
Normal file
8
README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# LIFE - LIFE is full ecosystem.
|
||||||
|
**Life-bot** - это бот связанный с `Telegram`. Он собирает статистику из разных сфер жизни.
|
||||||
|
|
||||||
|
Конечная цель данной системы - получение информации с максимального числа сервисов через API, её обработка и отображение в удобном формате. Система должна работать по принципу *минимума усилий*. То есть заполнение информации должно быть максимально простым и комфортным, а в идеале потребность системы в нём должна отсутствовать.
|
||||||
|
### На момент 18.07.2025:
|
||||||
|
- В качестве платформы для отображения информации и доступа к файлам (не исходникам) внутри системы выбран `Obsidian`
|
||||||
|
- Для синхронизации с `Obsidian` выбран WebDAV протокол
|
||||||
|
- Бот поддерживает только одного пользователя
|
||||||
11
compose.yml
Normal file
11
compose.yml
Normal file
@ -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
|
||||||
0
dockerfile
Normal file
0
dockerfile
Normal file
0
requirements.txt
Normal file
0
requirements.txt
Normal file
10
src/__main__.py
Normal file
10
src/__main__.py
Normal file
@ -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!")
|
||||||
6
src/config/credentials.py
Normal file
6
src/config/credentials.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from decouple import config
|
||||||
|
|
||||||
|
|
||||||
|
# Telegram
|
||||||
|
|
||||||
|
bot_token = config('BOT_TOKEN', default='')
|
||||||
3
src/config/options.py
Normal file
3
src/config/options.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from decouple import config
|
||||||
|
|
||||||
|
# todo
|
||||||
15
src/config/strings.py
Normal file
15
src/config/strings.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Bot Statuses
|
||||||
|
|
||||||
|
startBot = "Бот запущен!"
|
||||||
|
|
||||||
|
stopBot = "Бот остановлен!"
|
||||||
|
|
||||||
|
unexpectedError = "Возникла непредвиденная ошибка. :c"
|
||||||
|
|
||||||
|
# Commands
|
||||||
|
|
||||||
|
startCommand = "Привет! Я твой личный бот-трекер из системы LIFE."
|
||||||
|
|
||||||
|
helpCommand = "Для описания финансов пишите +число или -число. "
|
||||||
|
|
||||||
|
infoCommand = "Потрачено за сегодня:\nПолучено за сегодня:"
|
||||||
11
src/config/whitelist.py
Normal file
11
src/config/whitelist.py
Normal file
@ -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)]
|
||||||
90
src/telegram/controller.py
Normal file
90
src/telegram/controller.py
Normal file
@ -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)
|
||||||
18
todo.md
Normal file
18
todo.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Версия 0.x.x
|
||||||
|
### ToFix
|
||||||
|
- [ ] Мяу
|
||||||
|
|
||||||
|
### Новые функции
|
||||||
|
- [ ] Реализация взаимодействия с ботом через телеграмм
|
||||||
|
- - [ ] Реализация команд
|
||||||
|
- - - [x] Start
|
||||||
|
- - - [x] Help
|
||||||
|
- - - [ ] Info
|
||||||
|
- - [ ] Обработка других сообщений
|
||||||
|
- [ ] Реализация взаимодействия бота с WebDAV
|
||||||
|
- [ ] Конфигурация Obsidian
|
||||||
|
- [ ] Реализация развёртывания программы
|
||||||
|
- - [ ] Написать хорошую README.md
|
||||||
|
- - [ ] Написать compose.yml
|
||||||
|
- - [ ] Добавить requirements.txt
|
||||||
|
- - [ ] Добавить работу с gitea-runner
|
||||||
Reference in New Issue
Block a user