From 5c56f446189afb736663426b25d5df1bb82be94b Mon Sep 17 00:00:00 2001 From: JkLondon Date: Wed, 30 Jul 2025 18:32:35 +0200 Subject: [PATCH] initial commit --- Dockerfile | 11 +++++ docker-compose.yml | 14 ++++++ go.mod | 5 ++ go.sum | 2 + main.go | 120 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 152 insertions(+) create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1a91a01 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM golang:1.24.4 AS builder + +WORKDIR /app +COPY . . +RUN go mod tidy && go build -o bot main.go + +FROM debian:bookworm-slim +WORKDIR /app +RUN apt-get update && apt-get install -y ca-certificates && update-ca-certificates +COPY --from=builder /app/bot . +CMD ["./bot"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d39a52f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +version: "3.9" + +services: + todemon: + build: . + container_name: todemon + restart: always + env_file: + - .env + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..1b08148 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module git1337.ilyamikheev.com/ilyam/todemon + +go 1.24.4 + +require github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..db8e45c --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc= +github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8= diff --git a/main.go b/main.go new file mode 100644 index 0000000..a4c8506 --- /dev/null +++ b/main.go @@ -0,0 +1,120 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "net/http" + "os" + "strings" + "time" + + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" +) + +type Task struct { + ID string `json:"id"` + Content string `json:"content"` + Due *struct { + Date string `json:"date"` + } `json:"due"` +} + +var ( + todoistToken = os.Getenv("TODOIST_TOKEN") + telegramToken = os.Getenv("TELEGRAM_TOKEN") + chatID = os.Getenv("CHAT_ID") + bot *tgbotapi.BotAPI + overdueTasks = map[string]bool{} +) + +func getOverdueTasks() []Task { + log.Println("[INFO] Запрашиваю задачи из Todoist...") + req, _ := http.NewRequest("GET", "https://api.todoist.com/rest/v2/tasks", nil) + req.Header.Set("Authorization", "Bearer "+todoistToken) + + resp, err := http.DefaultClient.Do(req) + if err != nil { + log.Println("Ошибка запроса Todoist:", err) + return nil + } + defer resp.Body.Close() + + var tasks []Task + if err := json.NewDecoder(resp.Body).Decode(&tasks); err != nil { + log.Println("Ошибка парсинга задач:", err) + return nil + } + + now := time.Now().Format("2006-01-02T15:04") + var overdue []Task + for _, task := range tasks { + if task.Due != nil && strings.Compare(task.Due.Date, now) < 0 { + overdue = append(overdue, task) + } + } + return overdue +} + +func closeTask(taskID string) { + url := fmt.Sprintf("https://api.todoist.com/rest/v2/tasks/%s/close", taskID) + req, _ := http.NewRequest("POST", url, nil) + req.Header.Set("Authorization", "Bearer "+todoistToken) + http.DefaultClient.Do(req) +} + +func spamCheck() { + tasks := getOverdueTasks() + for _, task := range tasks { + if !overdueTasks[task.ID] { + msg := tgbotapi.NewMessage(toInt64(chatID), fmt.Sprintf("🔥 Просрочено: %s", task.Content)) + button := tgbotapi.NewInlineKeyboardMarkup( + tgbotapi.NewInlineKeyboardRow( + tgbotapi.NewInlineKeyboardButtonData("✅ Сделал", task.ID), + ), + ) + msg.ReplyMarkup = button + bot.Send(msg) + overdueTasks[task.ID] = true + } else { + bot.Send(tgbotapi.NewMessage(toInt64(chatID), "⏰ Ну что, сделал уже?!")) + } + } +} + +func toInt64(s string) int64 { + var n int64 + fmt.Sscan(s, &n) + return n +} + +func main() { + var err error + bot, err = tgbotapi.NewBotAPI(telegramToken) + if err != nil { + log.Fatal("Ошибка запуска бота:", err) + } + + log.Println("[INFO] Бот запущен") + + u := tgbotapi.NewUpdate(0) + u.Timeout = 60 + updates := bot.GetUpdatesChan(u) + + ticker := time.NewTicker(1 * time.Hour) + go func() { + spamCheck() + for range ticker.C { + spamCheck() + } + }() + + for update := range updates { + if update.CallbackQuery != nil { + taskID := update.CallbackQuery.Data + closeTask(taskID) + bot.Send(tgbotapi.NewMessage(update.CallbackQuery.Message.Chat.ID, "✅ Задача закрыта!")) + delete(overdueTasks, taskID) + } + } +}