working de/edit/complete funcs

This commit is contained in:
Casual 2024-07-03 05:51:53 +03:00
parent 6a4650cfd2
commit 43843c705d
6 changed files with 122 additions and 77 deletions

108
caldav.go
View File

@ -6,6 +6,7 @@ import (
webdav "github.com/emersion/go-webdav" webdav "github.com/emersion/go-webdav"
"github.com/emersion/go-webdav/caldav" "github.com/emersion/go-webdav/caldav"
"github.com/emersion/go-ical" "github.com/emersion/go-ical"
"github.com/teambition/rrule-go"
"strings" "strings"
"github.com/google/uuid" "github.com/google/uuid"
@ -496,10 +497,10 @@ func (m model) UploadTodo(event ical.Event) (err error) {
} }
func (m model) DelTodo(delUID string) (err error) { // func (m model) DelTodo(delUID string) (err error) {
// func (m model) DelTodo(todo ical.Event) (err error) { func (m model) DelTodo(todo ical.Event) (err error) {
// delUID,err := todo.Props.Get(ical.PropUID).Text() delUID,err := todo.Props.Get(ical.PropUID).Text()
// if err != nil {return} // if err != nil {return}
// calendar, err := client.GetCalendarObject(ctx, m.Creds.CalendarPath+delUID+".isc") // calendar, err := client.GetCalendarObject(ctx, m.Creds.CalendarPath+delUID+".isc")
@ -531,24 +532,20 @@ func (m model) DelTodo(delUID string) (err error) {
// URL: url.Parse(m.Creds.URL + m.Creds.CalendarPath + delUID + ".isc"), // URL: url.Parse(m.Creds.URL + m.Creds.CalendarPath + delUID + ".isc"),
// //
// } // }
client := &http.Client{}
client := &http.Client{}
parts := strings.Split(m.Creds.URL, "/") parts := strings.Split(m.Creds.URL, "/")
baseURL := parts[0]+"//"+parts[2] baseURL := parts[0]+"//"+parts[2]
// Create request // Create request
req, err := http.NewRequest("DELETE", baseURL + m.Creds.CalendarPath + delUID + ".isc", nil) req, err := http.NewRequest("DELETE", baseURL + m.Creds.CalendarPath + delUID + ".isc", nil)
if err != nil { if err != nil {return}
// fmt.Println(err)
return
}
req.SetBasicAuth(m.Creds.Username, m.Creds.Password) req.SetBasicAuth(m.Creds.Username, m.Creds.Password)
// Fetch Request // Fetch Request
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {return}
// fmt.Println(err) // resp.Body.Close()
return
}
defer resp.Body.Close() defer resp.Body.Close()
// Read Response Body // Read Response Body
@ -558,22 +555,66 @@ func (m model) DelTodo(delUID string) (err error) {
// return // return
// } // }
if resp.Status != "204 No Content" {return errors.New("Can't delete, response status: "+resp.Status+".")} if resp.Status == "204 No Content" {return nil}
if resp.Status == "404 Not Found" {
// Nextcloud Tasks create differend GUID for Vtodo and path
// TODO code fmt - Highway to for-if hell
for _, calObj := range m.CalObjects {
for _, eventComponent:= range (*calObj.Data).Children {
event := ical.Event{Component: eventComponent}
if event.Name == "VTODO" {
// eventUID,_ := (*event).Props["UID"][0].Text()
eventUID,err := event.Props.Get(ical.PropUID).Text()
if err != nil {eventUID = ""}
if (eventUID == delUID) {
//verify that it's indeed that event by comparing Name
sum1,err:=todo.Props.Get("SUMMARY").Text()
if err != nil {return err}
sum2,err:=event.Props.Get("SUMMARY").Text()
if err != nil {return err}
if sum1==sum2 {
req2, err := http.NewRequest("DELETE", baseURL + calObj.Path, nil)
if err != nil {return err}
req2.SetBasicAuth(m.Creds.Username, m.Creds.Password)
// Fetch Request
resp2, err := client.Do(req2)
if err != nil {return err}
defer resp2.Body.Close()
if resp2.Status == "204 No Content" {return nil} else {return errors.New("Can't delete, response status: "+resp2.Status+".")}
//TODO exit for loop
// return errors.New("test")
}
}
}
}
}
// return errors.New("test")
}
time.Sleep(2*time.Second) //TODO DEBUG RM ME
// Display Results // Display Results
// fmt.Println("response Status : ", resp.Status) // fmt.Println("response Status : ", resp.Status)
// fmt.Println("response Headers : ", resp.Header) // fmt.Println("response Headers : ", resp.Header)
// fmt.Println("response Body : ", string(respBody)) // fmt.Println("response Body : ", string(respBody))
return nil // return nil
return errors.New("Can't delete, response status: "+resp.Status+".")
} }
func (m model) EditTodo(todo ical.Event) (err error) { func (m model) EditTodo(todo ical.Event) (err error) {
//TODO is there proper edit function ??? //TODO is there proper edit function ???
uid,err := todo.Props.Get(ical.PropUID).Text() // uid,err := todo.Props.Get(ical.PropUID).Text()
if err != nil {return} // if err != nil {return}
err = m.DelTodo(uid) err = m.DelTodo(todo)
if err != nil {return} if err != nil {return}
err = m.UploadTodo(todo) err = m.UploadTodo(todo)
@ -589,7 +630,38 @@ func (m model) EditTodo(todo ical.Event) (err error) {
func (m model) CompleteTodo(todo ical.Event) (err error) { func (m model) CompleteTodo(todo ical.Event) (err error) {
//TODO if it repitable - Repeate, otherwise complete it //TODO if it repitable - Repeate, otherwise complete it
if todo.Props["RRULE"] != nil {
var rOptions *rrule.ROption
rOptions, err = todo.Props.RecurrenceRule()
if err != nil {return}
offset := rOptions.Interval
var currentDUE time.Time
currentDUE,err = todo.Props.DateTime("DUE",nil)
if err != nil {return}
switch rOptions.Freq {
case rrule.DAILY:
currentDUE = currentDUE.AddDate(0,0,offset)
case rrule.WEEKLY:
currentDUE = currentDUE.AddDate(0,0,7*offset)
case rrule.MONTHLY:
currentDUE = currentDUE.AddDate(0,offset,0)
case rrule.YEARLY:
currentDUE = currentDUE.AddDate(offset,0,0)
case rrule.HOURLY: //TODO didn't debug
currentDUE = currentDUE.Add(time.Hour * time.Duration(offset))
case rrule.MINUTELY: //TODO didn't debug
currentDUE = currentDUE.Add(time.Minute * time.Duration(offset))
case rrule.SECONDLY: //TODO didn't debug
currentDUE = currentDUE.Add(time.Second * time.Duration(offset))
}
todo.Props.SetDateTime("DUE",currentDUE)
} else {
todo.Props.SetText(ical.PropStatus,"COMPLETED")
todo.Props.SetText(ical.PropPercentComplete,"100")
todo.Props.SetDateTime(ical.PropCompleted,time.Now())
}
err = m.EditTodo(todo) err = m.EditTodo(todo)
if err != nil {return} if err != nil {return}

2
go.mod
View File

@ -10,6 +10,7 @@ require (
github.com/emersion/go-webdav v0.5.0 github.com/emersion/go-webdav v0.5.0
github.com/google/uuid v1.3.1 github.com/google/uuid v1.3.1
github.com/projectdiscovery/goflags v0.1.56 github.com/projectdiscovery/goflags v0.1.56
github.com/teambition/rrule-go v1.8.2
github.com/zalando/go-keyring v0.2.5 github.com/zalando/go-keyring v0.2.5
golang.org/x/term v0.18.0 golang.org/x/term v0.18.0
) )
@ -47,7 +48,6 @@ require (
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
github.com/teambition/rrule-go v1.8.2 // indirect
github.com/tidwall/gjson v1.14.3 // indirect github.com/tidwall/gjson v1.14.3 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/pretty v1.2.0 // indirect

67
main.go
View File

@ -16,12 +16,15 @@ import (
// "strconv" // "strconv"
// "github.com/charmbracelet/bubbles/list"
) )
// var waitGroup sync.WaitGroup // var waitGroup sync.WaitGroup
func errHandler(err error, message string) { func errHandler(err error, message string) {
if err != nil { if err != nil {
//TODO double err!=nil
//TODO copy error to clipboard
fmt.Printf("\n\n%s: %s\n", message, err) fmt.Printf("\n\n%s: %s\n", message, err)
os.Exit(1) os.Exit(1)
} }
@ -45,9 +48,14 @@ func main() {
errHandler(err, "Unexpected error (we couldn't initiate WebDAV/CalDAV client)") errHandler(err, "Unexpected error (we couldn't initiate WebDAV/CalDAV client)")
calendars, err = GetCalendars() calendars, err = GetCalendars()
errHandler(err, "Error getting calendars (incorrect url/login/password)") errHandler(err, "Error getting calendars (incorrect url/login/password)")
//TODO crushs START
var found bool var found bool
// var calPath string // var calPath string
if options.Calendar == "" {
m.LoginToCalendar()
// m.ActiveWindow = "login"
}
if options.Calendar != "" { if options.Calendar != "" {
for _,calendar := range calendars { for _,calendar := range calendars {
if calendar.Name == options.Calendar { if calendar.Name == options.Calendar {
@ -63,61 +71,16 @@ func main() {
} }
os.Exit(1) os.Exit(1)
} }
// fmt.Println(m)
m.LoginToCalendar() m.LoginToCalendar()
m.GatherTodos() m.CalendarToTodo()
// calendarObjects, err := GetTODOs(calPath) //TODO crushs End
// errHandler(err, "Error getting TODOs")
//
// today := time.Now() //TODO move to tui and remove it
// todayTodos, err := ParseDueDateTODOs(calendarObjects, today)
// tomorrow := time.Now().AddDate(0, 0, 1)
// tomorrowTodos, err := ParseDueDateTODOs(calendarObjects, tomorrow)
// //TODO remove it
// fmt.Println("In total we have", len(calendarObjects), "todos")
// //TODO remove it
// var itemsToday []list.Item
// var itemsTomorrow []list.Item
// for _, todo := range todayTodos {
// itemsToday = append(itemsToday, todo)
// }
// for _, todo := range tomorrowTodos {
// itemsTomorrow = append(itemsTomorrow, todo)
// }
//TODO remove it
m.GatherTodos()
// m.TodayTab = list.New(itemsToday, list.NewDefaultDelegate(), 0, 0)
// m.TodayTab.Title = "Today"
// m.TomorrowTab = list.New(itemsTomorrow, list.NewDefaultDelegate(), 0, 0)
// m.TomorrowTab.Title = "Tomorrow"
m.LoggedIn = true
m.ActiveWindow = "today"
} else {
//TODO go to calendars page
// m.LoggedIn = true
m.ActiveWindow = "calendarChoose"
// items := []list.Item{
// item("Ramen"),
// item("Tomato Soup"),
// item("Hamburgers"),
// item("Cheeseburgers"),
// item("Currywurst"),
// item("Okonomiyaki"),
// item("Pasta"),
// item("Fillet Mignon"),
// item("Caviar"),
// item("Just Wine"),
// }
} }
} else { } else {
//TODO I'm on a highway to (IfElse) hell! //TODO I'm on a highway to (IfElse) hell!
//TODO probably need to do more careful debug //TODO probably need to do more careful debug
@ -156,8 +119,8 @@ func main() {
// errHandler(err,"test fail2") // errHandler(err,"test fail2")
//DEBUG stuff //DEBUG stuff
//TODO if task have alarm - make a notification / play sound...
p := tea.NewProgram(m, tea.WithAltScreen()) p := tea.NewProgram(m, tea.WithAltScreen()) //TODO DEBUG bring me back
if _, err := p.Run(); err != nil { if _, err := p.Run(); err != nil {
fmt.Println("Error running program:", err) fmt.Println("Error running program:", err)
os.Exit(1) os.Exit(1)

View File

@ -68,7 +68,7 @@ func (options *Options) SanityCheck() error {
} }
} }
if options.Proxy != "" {os.Setenv("HTTP_PROXY", options.Proxy)} if options.Proxy != "" {os.Setenv("HTTPS_PROXY", options.Proxy)}
return nil return nil

View File

@ -2,7 +2,7 @@ package main
import ( import (
// "github.com/emersion/go-ical" "github.com/emersion/go-ical"
// "time" // "time"
"github.com/charmbracelet/bubbles/list" "github.com/charmbracelet/bubbles/list"
"github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/key"
@ -31,11 +31,13 @@ func (m model) newItemDelegate(keys *delegateKeyMap) list.DefaultDelegate {
d.UpdateFunc = func(msg tea.Msg, ml *list.Model) tea.Cmd { d.UpdateFunc = func(msg tea.Msg, ml *list.Model) tea.Cmd {
var title string var title string
var todoUID string // var todoUID string
var todoIcal ical.Event
if i, ok := ml.SelectedItem().(TODO); ok { if i, ok := ml.SelectedItem().(TODO); ok {
title = i.Title() title = i.Title()
todoUID = i.UID() // todoUID = i.UID()
todoIcal = ical.Event(i)
} else { } else {
return nil return nil
} }
@ -44,10 +46,17 @@ func (m model) newItemDelegate(keys *delegateKeyMap) list.DefaultDelegate {
case tea.KeyMsg: case tea.KeyMsg:
switch { switch {
case key.Matches(msg, keys.choose): case key.Matches(msg, keys.choose):
err := m.CompleteTodo(todoIcal)
if err != nil {return errHandler_tui(err,"can't complete item")}
index := ml.Index()
ml.RemoveItem(index)
if len(ml.Items()) == 0 {
keys.choose.SetEnabled(false)
}
return ml.NewStatusMessage(statusMessageStyle("You chose " + title)) return ml.NewStatusMessage(statusMessageStyle("You chose " + title))
case key.Matches(msg, keys.remove): case key.Matches(msg, keys.remove):
err := m.DelTodo(todoUID) err := m.DelTodo(todoIcal)
if err != nil {return errHandler_tui(err,"can't delete item")} if err != nil {return errHandler_tui(err,"can't delete item")}
index := ml.Index() index := ml.Index()
ml.RemoveItem(index) ml.RemoveItem(index)

View File

@ -41,9 +41,10 @@ func (i TODO) FilterValue() string {
func (m *model) GatherTodos() (err error) { func (m *model) GatherTodos() (err error) {
//TODO more modular approach //TODO more modular approach
calendarObjects, err := GetTODOs(m.Creds.CalendarPath) m.CalObjects, err = GetTODOs(m.Creds.CalendarPath)
if err != nil {return} if err != nil {return}
calendarObjects := m.CalObjects //TODO rm me
// var todayTodos []TODO // var todayTodos []TODO
today := time.Now() today := time.Now()