188 lines
5.8 KiB
Python
188 lines
5.8 KiB
Python
import os
|
||
from datetime import datetime
|
||
from dotenv import load_dotenv
|
||
from aiogram import Bot, Dispatcher
|
||
from aiogram.client.default import DefaultBotProperties
|
||
from aiogram.enums import ParseMode
|
||
from aiogram.filters import Command, CommandStart
|
||
from aiogram.types import Message
|
||
from trilium_py.client import ETAPI
|
||
|
||
load_dotenv()
|
||
|
||
|
||
TELEGRAM_TOKEN = os.getenv("TELEGRAM_TOKEN")
|
||
TRILIUM_URL = os.getenv("TRILIUM_URL")
|
||
TRILIUM_TOKEN = os.getenv("TRILIUM_TOKEN")
|
||
INBOX_NOTE_ID = os.getenv("INBOX_NOTE_ID")
|
||
DAILY_NOTE_ID = os.getenv("DAILY_NOTE_ID") # ID папки для ежедневных заметок
|
||
|
||
# создаем Trilium API клиент
|
||
ea = ETAPI(server_url=TRILIUM_URL, token=TRILIUM_TOKEN)
|
||
|
||
bot = Bot(token=TELEGRAM_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
|
||
|
||
dp = Dispatcher()
|
||
pending_daily_chats = set() # chat_ids ожидающих текст для /daily
|
||
|
||
|
||
@dp.message(CommandStart())
|
||
async def start(msg: Message):
|
||
await msg.answer("Отправь мне текст — я создам заметку в Trilium.")
|
||
|
||
|
||
def _get_id(obj):
|
||
if isinstance(obj, dict):
|
||
return obj.get("noteId") or obj.get("id")
|
||
return getattr(obj, "noteId", None) or getattr(obj, "id", None)
|
||
|
||
|
||
def _get_title(obj):
|
||
return obj.get("title") if isinstance(obj, dict) else getattr(obj, "title", "")
|
||
|
||
|
||
def _get_content(obj):
|
||
return obj.get("content") if isinstance(obj, dict) else getattr(obj, "content", "")
|
||
|
||
|
||
def _translate_month_en_ru(name: str) -> str:
|
||
mapping = {
|
||
"January": "Январь",
|
||
"February": "Февраль",
|
||
"March": "Март",
|
||
"April": "Апрель",
|
||
"May": "Май",
|
||
"June": "Июнь",
|
||
"July": "Июль",
|
||
"August": "Август",
|
||
"September": "Сентябрь",
|
||
"October": "Октябрь",
|
||
"November": "Ноябрь",
|
||
"December": "Декабрь",
|
||
}
|
||
return mapping.get(name, name)
|
||
|
||
|
||
def _translate_weekday_en_ru(name: str) -> str:
|
||
mapping = {
|
||
"Monday": "Понедельник",
|
||
"Tuesday": "Вторник",
|
||
"Wednesday": "Среда",
|
||
"Thursday": "Четверг",
|
||
"Friday": "Пятница",
|
||
"Saturday": "Суббота",
|
||
"Sunday": "Воскресенье",
|
||
}
|
||
return mapping.get(name, name)
|
||
|
||
|
||
def save_inbox(text: str):
|
||
# разделяем на заголовок и тело
|
||
lines = text.split("\n", 1)
|
||
title = lines[0][:100]
|
||
content = lines[1] if len(lines) > 1 else ""
|
||
ea.create_note(
|
||
parentNoteId=INBOX_NOTE_ID, title=title, content=content, type="text"
|
||
)
|
||
|
||
|
||
def save_daily(text: str) -> str:
|
||
today = datetime.now()
|
||
month_name = (
|
||
f"{today.strftime('%m')} - {_translate_month_en_ru(today.strftime('%B'))}"
|
||
)
|
||
day_name = (
|
||
f"{today.strftime('%d')} - {_translate_weekday_en_ru(today.strftime('%A'))}"
|
||
)
|
||
today_date = today.strftime("%Y-%m-%d")
|
||
|
||
# Корень daily
|
||
daily_root = ea.get_note(DAILY_NOTE_ID)
|
||
|
||
# Ищем/создаём месяц
|
||
month_folder = None
|
||
if hasattr(daily_root, "children"):
|
||
for child in daily_root.children:
|
||
if _get_title(child) == month_name:
|
||
month_folder = child
|
||
break
|
||
|
||
if not month_folder:
|
||
month_folder = ea.create_note(
|
||
parentNoteId=DAILY_NOTE_ID, title=month_name, type="text"
|
||
)
|
||
|
||
month_id = _get_id(month_folder)
|
||
month_folder = ea.get_note(month_id)
|
||
|
||
# Ищем/создаём день
|
||
day_folder = None
|
||
if hasattr(month_folder, "children"):
|
||
for child in month_folder.children:
|
||
if _get_title(child) == day_name:
|
||
day_folder = child
|
||
break
|
||
|
||
if not day_folder:
|
||
day_folder = ea.create_note(parentNoteId=month_id, title=day_name, type="text")
|
||
|
||
day_id = _get_id(day_folder)
|
||
day_folder = ea.get_note(day_id)
|
||
|
||
# Ищем заметку по дате
|
||
existing_note = None
|
||
if hasattr(day_folder, "children"):
|
||
for child in day_folder.children:
|
||
if _get_title(child) == today_date:
|
||
existing_note = child
|
||
break
|
||
|
||
if existing_note:
|
||
existing_content = _get_content(existing_note)
|
||
new_content = f"{existing_content}\n\n---\n{text}" if existing_content else text
|
||
ea.update_note(noteId=_get_id(existing_note), content=new_content)
|
||
return f"Добавлено в ежедневную заметку за {today_date}."
|
||
|
||
ea.create_note(parentNoteId=day_id, title=today_date, content=text, type="text")
|
||
return f"Создана ежедневная заметка за {today_date}."
|
||
|
||
|
||
@dp.message(Command("daily"))
|
||
async def daily_command(msg: Message):
|
||
pending_daily_chats.add(msg.chat.id)
|
||
await msg.answer(
|
||
"Жду текст для ежедневной заметки. Следующее сообщение запишу в текущий день."
|
||
)
|
||
|
||
|
||
@dp.message()
|
||
async def handler(msg: Message):
|
||
text = (msg.text or "").strip()
|
||
|
||
# Если ожидаем daily — пишем туда
|
||
if msg.chat.id in pending_daily_chats:
|
||
pending_daily_chats.discard(msg.chat.id)
|
||
try:
|
||
result = save_daily(text)
|
||
await msg.answer(result)
|
||
except Exception as e:
|
||
await msg.answer(f"Ошибка при работе с ежедневной заметкой: {str(e)}")
|
||
return
|
||
|
||
# Обычная заметка в Inbox
|
||
try:
|
||
save_inbox(text)
|
||
await msg.answer("Заметка сохранена в Trilium.")
|
||
except Exception as e:
|
||
await msg.answer(f"Ошибка при сохранении в Inbox: {str(e)}")
|
||
|
||
|
||
async def main():
|
||
await dp.start_polling(bot)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
import asyncio
|
||
|
||
asyncio.run(main())
|