mirror of
https://github.com/Xevion/todoist-late-reset.git
synced 2025-12-10 12:08:54 -06:00
new api organization
This commit is contained in:
54
internal/api/activity.go
Normal file
54
internal/api/activity.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
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 (sc *SyncClient) RecentlyCompleted() (*ActivityLog, error) {
|
||||||
|
params := url.Values{"event_type": {"completed"}}
|
||||||
|
req, err := http.NewRequest("GET", API_BASE_URL+"/activity/get?"+params.Encode(), 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
|
||||||
|
}
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
8
internal/api/helpers.go
Normal file
8
internal/api/helpers.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
// applyAuthorization sets the Authorization header with the API token.
|
||||||
|
func (sc *SyncClient) applyAuthorization(req *http.Request) {
|
||||||
|
req.Header.Set("Authorization", "Bearer "+sc.ApiToken)
|
||||||
|
}
|
||||||
23
internal/api/resource.go
Normal file
23
internal/api/resource.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
type ResourceType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Labels ResourceType = "labels"
|
||||||
|
Projects ResourceType = "projects"
|
||||||
|
Items ResourceType = "items"
|
||||||
|
Notes ResourceType = "notes"
|
||||||
|
Sections ResourceType = "sections"
|
||||||
|
Filters ResourceType = "filters"
|
||||||
|
Reminders ResourceType = "reminders"
|
||||||
|
RemindersLocation ResourceType = "reminders_location"
|
||||||
|
Locations ResourceType = "locations"
|
||||||
|
User ResourceType = "user"
|
||||||
|
LiveNotifications ResourceType = "live_notifications"
|
||||||
|
Collaborators ResourceType = "collaborators"
|
||||||
|
UserSettings ResourceType = "user_settings"
|
||||||
|
NotificationSettings ResourceType = "notification_settings"
|
||||||
|
UserPlanLimits ResourceType = "user_plan_limits"
|
||||||
|
CompletedInfo ResourceType = "completed_info"
|
||||||
|
Stats ResourceType = "stats"
|
||||||
|
)
|
||||||
@@ -1 +1,28 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
|
type ClientState struct {
|
||||||
|
// Items map[string]Item
|
||||||
|
}
|
||||||
|
|
||||||
|
type Changes struct {
|
||||||
|
Added []string
|
||||||
|
Updated []string
|
||||||
|
Deleted []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// sync synchronizes the client's state with the server. If the full parameter is set to true,
|
||||||
|
// a full synchronization is performed, otherwise, a partial synchronization is done.
|
||||||
|
// This strongly mutates the client's state.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
//
|
||||||
|
// full - a boolean indicating whether to perform a full synchronization.
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
//
|
||||||
|
// int - the number of changes synchronized.
|
||||||
|
// *Changes - a pointer to a Changes struct containing the details of the changes.
|
||||||
|
// error - an error object if an error occurred during synchronization, otherwise nil.
|
||||||
|
func (sc *SyncClient) sync(full bool) (int, *Changes, error) {
|
||||||
|
return 0, nil, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,16 +1,47 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"runtime"
|
||||||
|
"runtime/debug"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
userAgent string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
revision := "unknown"
|
||||||
|
version := "v0.0.0"
|
||||||
|
if info, ok := debug.ReadBuildInfo(); ok {
|
||||||
|
if info.Main.Version != "(devel)" {
|
||||||
|
version = info.Main.Version
|
||||||
|
revision = info.Main.Sum
|
||||||
|
} else {
|
||||||
|
fmt.Println("WARN : Inaccurate version information")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
userAgent = fmt.Sprintf("todoist-late-reset/%v (%v; revision %v)", version, runtime.GOOS, revision)
|
||||||
|
fmt.Println(userAgent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncClient represents a client for synchronizing data with the Todoist API.
|
||||||
|
// It holds the HTTP client, synchronization tokens, timestamps of the last syncs,
|
||||||
|
// and the types of resources to be synchronized.
|
||||||
type SyncClient struct {
|
type SyncClient struct {
|
||||||
Http *http.Client
|
Http *http.Client
|
||||||
SyncToken string
|
SyncToken string
|
||||||
ApiToken string
|
ApiToken string
|
||||||
|
// LastSync is the timestamp of the last synchronization, full or incremental.
|
||||||
LastSync time.Time
|
LastSync time.Time
|
||||||
|
// LastFullSync is the timestamp of the last full synchronization.
|
||||||
LastFullSync time.Time
|
LastFullSync time.Time
|
||||||
|
// RequireFullSync indicates that client state has changed that a full sync is warranted.
|
||||||
|
RequireFullSync bool
|
||||||
|
ResourceTypes map[ResourceType]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSyncClient(apiToken string) *SyncClient {
|
func NewSyncClient(apiToken string) *SyncClient {
|
||||||
@@ -21,22 +52,36 @@ func NewSyncClient(apiToken string) *SyncClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SyncResponse struct {
|
// UseResources marks the resource types to be synchronized.
|
||||||
|
func (sc *SyncClient) UseResources(resourceTypes ...ResourceType) {
|
||||||
|
for _, resourceType := range resourceTypes {
|
||||||
|
if resourceType != Items {
|
||||||
|
// Log a warning or handle the case where the resource type is not implemented
|
||||||
|
fmt.Printf("WARN : Resource type %v not implemented\n", resourceType)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if sc.ResourceTypes[resourceType] == false {
|
||||||
|
sc.ResourceTypes[resourceType] = true
|
||||||
|
|
||||||
|
// Incremental sync may not contain all necessary data, so require a full sync.
|
||||||
|
sc.RequireFullSync = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActivityLog struct {
|
// get performs a GET request to the Todoist API, building a request with the given path and parameters.
|
||||||
Count int `json:"count"`
|
// It will also apply Authorization, Content-Type, Accept, and User-Agent headers.
|
||||||
Events []Event `json:"events"`
|
func (sc *SyncClient) get(path string, params url.Values) (*http.Response, error) {
|
||||||
}
|
req, err := http.NewRequest("GET", API_BASE_URL+path+"?"+params.Encode(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
type Event struct {
|
req.Header.Set("Authorization", "Bearer "+sc.ApiToken)
|
||||||
EventDate time.Time `json:"event_date"`
|
req.Header.Set("Content-Type", "application/json")
|
||||||
EventType string `json:"event_type"`
|
req.Header.Set("Accept", "application/json")
|
||||||
ExtraData map[string]any `json:"extra_data"`
|
req.Header.Set("User-Agent", userAgent)
|
||||||
ExtraDataID int64 `json:"extra_data_id"`
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
|
|
||||||
InitiatorID *int64 `json:"initiator_id"`
|
return sc.Http.Do(req)
|
||||||
ObjectID string `json:"object_id"`
|
|
||||||
ObjectType string `json:"object_type"`
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user