initial commit
This commit is contained in:
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@ -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"]
|
||||||
14
docker-compose.yml
Normal file
14
docker-compose.yml
Normal file
@ -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"
|
||||||
5
go.mod
Normal file
5
go.mod
Normal file
@ -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
|
||||||
2
go.sum
Normal file
2
go.sum
Normal file
@ -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=
|
||||||
120
main.go
Normal file
120
main.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user