Files
todoist-late-reset/main.go

124 lines
3.1 KiB
Go

// Uses go cron to schedule a job to run every 3 minutes from 1AM to 3AM.
// Queries the todoist API for task completion
// Tasks that are completed between 12AM and 3AM are considered 'not too late' and will be rescheduled one day earlier (if they are recurring tasks).
// Only tasks with the included label (e.g. well-being) are considered.
// Most tasks are scheduled daily, so this means they'll be rescheduled for the current day. But not all.
package main
import (
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
_ "time/tzdata"
"github.com/go-co-op/gocron/v2"
"github.com/joho/godotenv"
)
var (
todoistApiToken string
redisURL string
cronSchedule string
tzLocation *time.Location
client = &http.Client{}
)
func init() {
// Load .env file if available
err := godotenv.Load()
if err != nil {
fmt.Println(".env file not loaded")
}
// Load timezone
tzLocation, err = time.LoadLocation("America/Chicago")
if err != nil {
fmt.Println("Error loading location:", err)
os.Exit(1)
}
}
func primary() error {
log, err := getRecentlyCompleted()
if err != nil {
fmt.Println("Error getting recently completed tasks:", err)
return err
}
now := time.Now().In(tzLocation)
startTime := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, tzLocation)
endTime := startTime.Add(3 * time.Hour)
for _, event := range log.Events {
if event.EventDate.After(startTime) && event.EventDate.Before(endTime) {
fmt.Printf("%s - %s\n", event.EventDate.In(tzLocation).Format("Monday, January 2, 3:04 PM MST"), event.ExtraData["content"])
}
}
return nil
}
func main() {
todoistApiToken = os.Getenv("TODOIST_API_KEY")
redisURL = os.Getenv("REDIS_URL")
cronSchedule = os.Getenv("CRON_SCHEDULE")
// opt, _ := redis.ParseURL(redisURL)
// client := redis.NewClient(opt)
// create a scheduler
s, err := gocron.NewScheduler(gocron.WithLocation(tzLocation))
if err != nil {
fmt.Println("Error creating scheduler:", err)
os.Exit(1)
}
// add a job to the scheduler
j, err := s.NewJob(
gocron.CronJob(cronSchedule, false),
gocron.NewTask(primary),
)
if err != nil {
fmt.Println("Error adding job to scheduler:", err)
os.Exit(1)
}
// Start the scheduler
s.Start()
nextRun, err := j.NextRun()
if err != nil {
fmt.Println("Error getting next run time:", err)
os.Exit(1)
}
durationUntilNextRun := time.Until(nextRun).Seconds()
fmt.Printf("startup: next run in %.2f seconds: %v\n", durationUntilNextRun, nextRun.Format(time.RFC3339))
if durationUntilNextRun > 1 {
// Run the job immediately
err = j.RunNow()
fmt.Println("startup: running job immediately")
if err != nil {
fmt.Println("Error running job immediately:", err)
os.Exit(1)
}
}
// Setup signal handler channel
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt) // Ctrl+C signal
signal.Notify(stop, syscall.SIGTERM) // Container stop signal
// Wait for signal (indefinite)
closingSignal := <-stop
fmt.Println("Gracefully shutting down, received signal:", closingSignal.String())
err = s.Shutdown()
if err != nil {
// handle error
}
}