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) } } }