mirror of
https://github.com/Xevion/todoist-late-reset.git
synced 2025-12-05 23:16:36 -06:00
reorganize into /cmd & /internal
This commit is contained in:
72
api.go
72
api.go
@@ -1,72 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
syncToken string
|
|
||||||
)
|
|
||||||
|
|
||||||
type ActivityLog struct {
|
|
||||||
Count int `json:"count"`
|
|
||||||
Events []Event `json:"events"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Event struct {
|
|
||||||
EventDate time.Time `json:"event_date"`
|
|
||||||
EventType string `json:"event_type"`
|
|
||||||
ExtraData map[string]any `json:"extra_data"`
|
|
||||||
ExtraDataID int64 `json:"extra_data_id"`
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
|
|
||||||
InitiatorID *int64 `json:"initiator_id"`
|
|
||||||
ObjectID string `json:"object_id"`
|
|
||||||
ObjectType string `json:"object_type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRecentlyCompleted() (*ActivityLog, error) {
|
|
||||||
baseURL := "https://api.todoist.com/sync/v9/activity/get"
|
|
||||||
params := url.Values{}
|
|
||||||
params.Add("event_type", "completed")
|
|
||||||
|
|
||||||
fullURL := baseURL + "?" + params.Encode()
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", fullURL, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("Authorization", "Bearer "+todoistApiToken)
|
|
||||||
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var activityLog *ActivityLog
|
|
||||||
if err := json.Unmarshal(body, &activityLog); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return activityLog, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// $ curl https://api.todoist.com/sync/v9/sync \
|
|
||||||
// -H "Authorization: Bearer 0123456789abcdef0123456789abcdef01234567" \
|
|
||||||
// -d sync_token='*' \
|
|
||||||
// -d resource_types='["all"]'
|
|
||||||
|
|
||||||
func synchronize() {
|
|
||||||
|
|
||||||
}
|
|
||||||
0
cmd/develop/main.go
Normal file
0
cmd/develop/main.go
Normal file
@@ -7,7 +7,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"internal/api"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
@@ -19,11 +19,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
todoistApiToken string
|
client *api.SyncClient
|
||||||
redisURL string
|
redisURL string
|
||||||
cronSchedule string
|
cronSchedule string
|
||||||
tzLocation *time.Location
|
tzLocation *time.Location
|
||||||
client = &http.Client{}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -41,31 +40,31 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// primary is the main function that will be run by the scheduler
|
||||||
func primary() error {
|
func primary() error {
|
||||||
log, err := getRecentlyCompleted()
|
// Get recently completed tasks
|
||||||
|
|
||||||
|
log, err := client.RecentlyCompleted()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error getting recently completed tasks:", err)
|
fmt.Println("Error fetching recently completed tasks:", err)
|
||||||
return 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 {
|
for _, event := range log.Events {
|
||||||
if event.EventDate.After(startTime) && event.EventDate.Before(endTime) {
|
// if event.EventDate.In(tzLocation).Hour() >= 1 && event.EventDate.In(tzLocation).Hour() < 3 {
|
||||||
fmt.Printf("%s - %s\n", event.EventDate.In(tzLocation).Format("Monday, January 2, 3:04 PM MST"), event.ExtraData["content"])
|
fmt.Printf("Task completed: %s at %s\n", event.ExtraData["content"], event.EventDate.In(tzLocation).Format("Monday, January 2, 3:04 PM MST"))
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
todoistApiToken = os.Getenv("TODOIST_API_KEY")
|
|
||||||
redisURL = os.Getenv("REDIS_URL")
|
redisURL = os.Getenv("REDIS_URL")
|
||||||
cronSchedule = os.Getenv("CRON_SCHEDULE")
|
cronSchedule = os.Getenv("CRON_SCHEDULE")
|
||||||
|
|
||||||
|
client = api.NewSyncClient(os.Getenv("TODOIST_API_KEY"))
|
||||||
|
|
||||||
// opt, _ := redis.ParseURL(redisURL)
|
// opt, _ := redis.ParseURL(redisURL)
|
||||||
// client := redis.NewClient(opt)
|
// client := redis.NewClient(opt)
|
||||||
|
|
||||||
@@ -97,7 +96,7 @@ func main() {
|
|||||||
durationUntilNextRun := time.Until(nextRun).Seconds()
|
durationUntilNextRun := time.Until(nextRun).Seconds()
|
||||||
fmt.Printf("startup: next run in %.2f seconds: %v\n", durationUntilNextRun, nextRun.Format(time.RFC3339))
|
fmt.Printf("startup: next run in %.2f seconds: %v\n", durationUntilNextRun, nextRun.Format(time.RFC3339))
|
||||||
|
|
||||||
if durationUntilNextRun > 1 {
|
if durationUntilNextRun > 60 {
|
||||||
// Run the job immediately
|
// Run the job immediately
|
||||||
err = j.RunNow()
|
err = j.RunNow()
|
||||||
fmt.Println("startup: running job immediately")
|
fmt.Println("startup: running job immediately")
|
||||||
@@ -118,6 +117,7 @@ func main() {
|
|||||||
fmt.Println("Gracefully shutting down, received signal:", closingSignal.String())
|
fmt.Println("Gracefully shutting down, received signal:", closingSignal.String())
|
||||||
err = s.Shutdown()
|
err = s.Shutdown()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// handle error
|
fmt.Println("Error shutting down scheduler:", err)
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
4
go.mod
4
go.mod
@@ -13,3 +13,7 @@ require (
|
|||||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
|
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
require internal/api v1.0.0
|
||||||
|
replace internal/api => ./internal/api
|
||||||
45
internal/api/commands.go
Normal file
45
internal/api/commands.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (sc *SyncClient) RecentlyCompleted() (*ActivityLog, error) {
|
||||||
|
baseURL := API_BASE_URL + "/activity/get"
|
||||||
|
params := url.Values{}
|
||||||
|
params.Add("event_type", "completed")
|
||||||
|
|
||||||
|
fullURL := baseURL + "?" + params.Encode()
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", fullURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Authorization", "Bearer "+sc.ApiToken)
|
||||||
|
|
||||||
|
resp, err := sc.Http.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var activityLog *ActivityLog
|
||||||
|
if err := json.Unmarshal(body, &activityLog); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return activityLog, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sc *SyncClient) sync() {
|
||||||
|
// Implementation for synchronize function
|
||||||
|
}
|
||||||
5
internal/api/constants.go
Normal file
5
internal/api/constants.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
var (
|
||||||
|
API_BASE_URL = "https://api.todoist.com/sync/v9"
|
||||||
|
)
|
||||||
4
internal/api/go.mod
Normal file
4
internal/api/go.mod
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
module api
|
||||||
|
|
||||||
|
go 1.22.3
|
||||||
|
|
||||||
1
internal/api/sync.go
Normal file
1
internal/api/sync.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package api
|
||||||
42
internal/api/types.go
Normal file
42
internal/api/types.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SyncClient struct {
|
||||||
|
Http *http.Client
|
||||||
|
SyncToken string
|
||||||
|
ApiToken string
|
||||||
|
LastSync time.Time
|
||||||
|
LastFullSync time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSyncClient(apiToken string) *SyncClient {
|
||||||
|
return &SyncClient{
|
||||||
|
Http: &http.Client{},
|
||||||
|
ApiToken: apiToken,
|
||||||
|
SyncToken: "*",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type SyncResponse struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActivityLog struct {
|
||||||
|
Count int `json:"count"`
|
||||||
|
Events []Event `json:"events"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Event struct {
|
||||||
|
EventDate time.Time `json:"event_date"`
|
||||||
|
EventType string `json:"event_type"`
|
||||||
|
ExtraData map[string]any `json:"extra_data"`
|
||||||
|
ExtraDataID int64 `json:"extra_data_id"`
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
|
||||||
|
InitiatorID *int64 `json:"initiator_id"`
|
||||||
|
ObjectID string `json:"object_id"`
|
||||||
|
ObjectType string `json:"object_type"`
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user