From 302fbc3a9db675c24e3ca2cb0c99d1ae5b88180e Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 11:47:26 +0200 Subject: time_entry.go: Rewrite `TimeEntry` type for the new era Change [Client, Project, Module, Task, WorkType] fields to `int`s instead of strings. In the new era, with config2.toml, these fields will be populated directly with the proper int IDs from TimeTask. Thus these fields need to be `int`s. Get rid of the `UnmarshalYAML` function as in the new era we won't be submitting time entries by YAML file. Instead they will be submitted directly via command line arguments (plus the IDs coming from the config file). --- timetask/time_entry.go | 47 +++++------------------------------------------ 1 file changed, 5 insertions(+), 42 deletions(-) diff --git a/timetask/time_entry.go b/timetask/time_entry.go index 17a8e0c..1cc4203 100644 --- a/timetask/time_entry.go +++ b/timetask/time_entry.go @@ -3,50 +3,13 @@ package timetask import "time" type TimeEntry struct { - Client string - Project string - Module string - Task string - WorkType string `yaml:"work_type"` + Client int + Project int + Module int + Task int + WorkType int Date time.Time Time int Billable bool Description string } - -// Parse date string into a real date -func (te *TimeEntry) UnmarshalYAML(unmarshal func(interface{}) error) error { - var auxiliary struct { - Client string - Project string - Module string - Task string - WorkType string `yaml:"work_type"` - Date string - Time int - Billable bool - Description string - } - - err := unmarshal(&auxiliary) - if err != nil { - return err - } - - date, err := time.Parse("2006-01-02", auxiliary.Date) - if auxiliary.Date != "" && err != nil { - return err - } - - te.Client = auxiliary.Client - te.Project = auxiliary.Project - te.Module = auxiliary.Module - te.Task = auxiliary.Task - te.WorkType = auxiliary.WorkType - te.Date = date - te.Time = auxiliary.Time - te.Billable = auxiliary.Billable - te.Description = auxiliary.Description - - return nil -} -- cgit v1.2.3 From bd1a9e85c2ee87017208772b88190b75319874d2 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 12:00:17 +0200 Subject: http.go: Restore `SubmitTimeEntries` & `buildSubmissionParams` Uncomment these functions. Looks like they'll still be useful after all. Just need a little munging to fit them into the usage of submitting a single time entry and using our new `Project` and `TimeEntry` types. --- timetask/http.go | 212 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 109 insertions(+), 103 deletions(-) diff --git a/timetask/http.go b/timetask/http.go index 94a1597..4832d00 100644 --- a/timetask/http.go +++ b/timetask/http.go @@ -36,106 +36,112 @@ func Login(username, password string) (resp *http.Response, err error) { return resp, err } -// func SubmitTimeEntries(fields Fields, time_entries []TimeEntry) (resp *http.Response, err error) { -// v := buildSubmissionParams(fields, time_entries) -// -// v.Set("module", "time") -// v.Set("action", "submitmultipletime") -// -// return nil, nil -// } -// -// func buildSubmissionParams(fields Fields, time_entries []TimeEntry) url.Values { -// v := url.Values{} -// entry_indexes := []string{} -// -// for i, entry := range time_entries { -// entry_indexes = append(entry_indexes, strconv.Itoa(i)) -// -// client, err := fields.ClientByName(entry.Client) -// if err != nil { -// log.Panic(err) -// } -// -// project, err := client.ProjectByName(entry.Project) -// if err != nil { -// log.Panic(err) -// } -// -// module, err := project.ModuleByName(entry.Module) -// if err != nil { -// log.Panic(err) -// } -// -// task, err := project.TaskByName(entry.Task) -// if err != nil { -// log.Panic(err) -// } -// -// work_type, err := project.WorkTypeByName(entry.WorkType) -// if err != nil { -// log.Panic(err) -// } -// -// var billable string -// if entry.Billable { -// billable = "t" -// } else { -// billable = "f" -// } -// -// v.Set( -// fmt.Sprintf("f_personID%d", i), -// strconv.Itoa(fields.PersonID), -// ) -// -// v.Set( -// fmt.Sprintf("f_clientID%d", i), -// strconv.Itoa(client.ID), -// ) -// -// v.Set( -// fmt.Sprintf("f_projectID%d", i), -// strconv.Itoa(project.ID), -// ) -// -// v.Set( -// fmt.Sprintf("f_moduleID%d", i), -// strconv.Itoa(module.ID), -// ) -// -// v.Set( -// fmt.Sprintf("f_taskID%d", i), -// strconv.Itoa(task.ID), -// ) -// -// v.Set( -// fmt.Sprintf("f_worktypeID%d", i), -// strconv.Itoa(work_type.ID), -// ) -// -// v.Set( -// fmt.Sprintf("f_date%d", i), -// entry.Date.Format("02/01/06"), // day/month/year -// ) -// -// v.Set( -// fmt.Sprintf("f_time%d", i), -// strconv.Itoa(entry.Time), -// ) -// -// v.Set( -// fmt.Sprintf("f_billable%d", i), -// billable, -// ) -// -// v.Set( -// fmt.Sprintf("f_description%d", i), -// entry.Description, -// ) -// } -// -// v.Set("f_entryIndexes", strings.Join(entry_indexes, ",")) -// -// return v -// } +func SubmitTimeEntry( + project Project, + time_entry TimeEntry, +) (resp *http.Response, err error) { +} + +func SubmitTimeEntries(fields Fields, time_entries []TimeEntry) (resp *http.Response, err error) { + v := buildSubmissionParams(fields, time_entries) + + v.Set("module", "time") + v.Set("action", "submitmultipletime") + + return nil, nil +} + +func buildSubmissionParams(fields Fields, time_entries []TimeEntry) url.Values { + v := url.Values{} + entry_indexes := []string{} + + for i, entry := range time_entries { + entry_indexes = append(entry_indexes, strconv.Itoa(i)) + + client, err := fields.ClientByName(entry.Client) + if err != nil { + log.Panic(err) + } + + project, err := client.ProjectByName(entry.Project) + if err != nil { + log.Panic(err) + } + + module, err := project.ModuleByName(entry.Module) + if err != nil { + log.Panic(err) + } + + task, err := project.TaskByName(entry.Task) + if err != nil { + log.Panic(err) + } + + work_type, err := project.WorkTypeByName(entry.WorkType) + if err != nil { + log.Panic(err) + } + + var billable string + if entry.Billable { + billable = "t" + } else { + billable = "f" + } + + v.Set( + fmt.Sprintf("f_personID%d", i), + strconv.Itoa(fields.PersonID), + ) + + v.Set( + fmt.Sprintf("f_clientID%d", i), + strconv.Itoa(client.ID), + ) + + v.Set( + fmt.Sprintf("f_projectID%d", i), + strconv.Itoa(project.ID), + ) + + v.Set( + fmt.Sprintf("f_moduleID%d", i), + strconv.Itoa(module.ID), + ) + + v.Set( + fmt.Sprintf("f_taskID%d", i), + strconv.Itoa(task.ID), + ) + + v.Set( + fmt.Sprintf("f_worktypeID%d", i), + strconv.Itoa(work_type.ID), + ) + + v.Set( + fmt.Sprintf("f_date%d", i), + entry.Date.Format("02/01/06"), // day/month/year + ) + + v.Set( + fmt.Sprintf("f_time%d", i), + strconv.Itoa(entry.Time), + ) + + v.Set( + fmt.Sprintf("f_billable%d", i), + billable, + ) + + v.Set( + fmt.Sprintf("f_description%d", i), + entry.Description, + ) + } + + v.Set("f_entryIndexes", strings.Join(entry_indexes, ",")) + + return v +} -- cgit v1.2.3 From 810b140b4a29b1159e76b51b90b9be7d22df1c3e Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 12:08:07 +0200 Subject: buildSubmissionParams(): Support new `TimeEntry`; Submit single entry Change the function to use our new `TimeEntry` type, which doesn't demand asking for IDs as it already has them built in. Additionally, remove the loop here as we only want to submit a single time entry at a time. Add a new `Profile` type that holds onto the user's person_id. Forgot that existed. We'll have users fill that into their config.toml file. --- timetask/http.go | 146 ++++++++++++++++++++-------------------------------- timetask/profile.go | 5 ++ 2 files changed, 62 insertions(+), 89 deletions(-) create mode 100644 timetask/profile.go diff --git a/timetask/http.go b/timetask/http.go index 4832d00..8b90230 100644 --- a/timetask/http.go +++ b/timetask/http.go @@ -6,7 +6,7 @@ import ( "net/http" "net/http/cookiejar" "net/url" - // "strconv" + "strconv" // "strings" "golang.org/x/net/publicsuffix" @@ -51,97 +51,65 @@ func SubmitTimeEntries(fields Fields, time_entries []TimeEntry) (resp *http.Resp return nil, nil } -func buildSubmissionParams(fields Fields, time_entries []TimeEntry) url.Values { +func buildSubmissionParams(profile Profile, time_entry TimeEntry) url.Values { v := url.Values{} - entry_indexes := []string{} - - for i, entry := range time_entries { - entry_indexes = append(entry_indexes, strconv.Itoa(i)) - - client, err := fields.ClientByName(entry.Client) - if err != nil { - log.Panic(err) - } - - project, err := client.ProjectByName(entry.Project) - if err != nil { - log.Panic(err) - } - - module, err := project.ModuleByName(entry.Module) - if err != nil { - log.Panic(err) - } - - task, err := project.TaskByName(entry.Task) - if err != nil { - log.Panic(err) - } - - work_type, err := project.WorkTypeByName(entry.WorkType) - if err != nil { - log.Panic(err) - } - - var billable string - if entry.Billable { - billable = "t" - } else { - billable = "f" - } - - v.Set( - fmt.Sprintf("f_personID%d", i), - strconv.Itoa(fields.PersonID), - ) - - v.Set( - fmt.Sprintf("f_clientID%d", i), - strconv.Itoa(client.ID), - ) - - v.Set( - fmt.Sprintf("f_projectID%d", i), - strconv.Itoa(project.ID), - ) - - v.Set( - fmt.Sprintf("f_moduleID%d", i), - strconv.Itoa(module.ID), - ) - - v.Set( - fmt.Sprintf("f_taskID%d", i), - strconv.Itoa(task.ID), - ) - - v.Set( - fmt.Sprintf("f_worktypeID%d", i), - strconv.Itoa(work_type.ID), - ) - - v.Set( - fmt.Sprintf("f_date%d", i), - entry.Date.Format("02/01/06"), // day/month/year - ) - - v.Set( - fmt.Sprintf("f_time%d", i), - strconv.Itoa(entry.Time), - ) - - v.Set( - fmt.Sprintf("f_billable%d", i), - billable, - ) - - v.Set( - fmt.Sprintf("f_description%d", i), - entry.Description, - ) + + v.Set( + "f_personID0", + strconv.Itoa(profile.PersonID), + ) + + v.Set( + "f_clientID0", + strconv.Itoa(time_entry.Client), + ) + + v.Set( + "f_projectID0", + strconv.Itoa(time_entry.Project), + ) + + v.Set( + "f_moduleID0", + strconv.Itoa(time_entry.Module), + ) + + v.Set( + "f_taskID0", + strconv.Itoa(time_entry.Task), + ) + + v.Set( + "f_worktypeID0", + strconv.Itoa(time_entry.WorkType), + ) + + v.Set( + "f_date0", + time_entry.Date.Format("02/01/06"), // day/month/year + ) + + v.Set( + "f_time0", + strconv.Itoa(time_entry.Time), + ) + + var billable string + if time_entry.Billable { + billable = "t" + } else { + billable = "f" } - v.Set("f_entryIndexes", strings.Join(entry_indexes, ",")) + v.Set( + "f_billable0", + billable, + ) + + v.Set( + "f_description0", + time_entry.Description, + ) return v } diff --git a/timetask/profile.go b/timetask/profile.go new file mode 100644 index 0000000..66e9197 --- /dev/null +++ b/timetask/profile.go @@ -0,0 +1,5 @@ +package timetask + +type Profile struct { + PersonID int +} -- cgit v1.2.3 From 44cb0e11566c7416c8859dac18baf24a0337ecce Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 12:14:44 +0200 Subject: Project: Add a TOML tag for the WorkType field Otherwise the TOML decoder didn't know how to parse it. --- timetask/fields.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/timetask/fields.go b/timetask/fields.go index da2b37d..f535d92 100644 --- a/timetask/fields.go +++ b/timetask/fields.go @@ -21,7 +21,7 @@ type Project struct { Project int Module int Task int - WorkType int + WorkType int `toml:"work_type"` Time int Billable bool } -- cgit v1.2.3 From 1576d4111d412a1c501b6a8630c4d559302b9b21 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 12:16:33 +0200 Subject: main.go: Add `Profile` to `Config` Require the config.toml file to come with a `[profile]` hash. This allows us to get the "person_id" for correct submission to TimeTask. Additionally, add a TOML tag to `PersonID` in `Profile` to allow it to be decoded. --- main.go | 1 + timetask/profile.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index ccdcaed..aea2112 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ type Config struct { Username string PasswordCmd string } + Profile timetask.Profile Projects map[string]timetask.Project } diff --git a/timetask/profile.go b/timetask/profile.go index 66e9197..9267ee6 100644 --- a/timetask/profile.go +++ b/timetask/profile.go @@ -1,5 +1,5 @@ package timetask type Profile struct { - PersonID int + PersonID int `toml:"person_id"` } -- cgit v1.2.3 From 758cf0bf7e899acee89ee4b8a39c5565622aee31 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 12:42:35 +0200 Subject: http.go: Replace `SubmitTimeEntries` with `SubmitTimeEntry` A slightly altered function that only submits a single time entry and uses our new `Profile`, `Project`, and `TimeEntry` types. --- timetask/http.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/timetask/http.go b/timetask/http.go index 8b90230..76bfdc3 100644 --- a/timetask/http.go +++ b/timetask/http.go @@ -37,13 +37,11 @@ func Login(username, password string) (resp *http.Response, err error) { } func SubmitTimeEntry( + profile Profile, project Project, time_entry TimeEntry, ) (resp *http.Response, err error) { -} - -func SubmitTimeEntries(fields Fields, time_entries []TimeEntry) (resp *http.Response, err error) { - v := buildSubmissionParams(fields, time_entries) + v := buildSubmissionParams(profile, time_entry) v.Set("module", "time") v.Set("action", "submitmultipletime") @@ -51,6 +49,7 @@ func SubmitTimeEntries(fields Fields, time_entries []TimeEntry) (resp *http.Resp return nil, nil } + func buildSubmissionParams(profile Profile, time_entry TimeEntry) url.Values { v := url.Values{} -- cgit v1.2.3 From f017c462593496efbc0810ec2603da49a2e3d9d8 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 13:02:03 +0200 Subject: Add `NewTimeEntry()` A new function that creates a `TimeEntry` build from a `Profile`, `Project`, and a few other parameters. Makes it a bit easier to create `TimeEntry`ies. Additionally, add a `PersonID` field to `TimeEntry` so we can pass it around as a self-contained thing without worrying about having to pass a `Profile` along with it. --- timetask/time_entry.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/timetask/time_entry.go b/timetask/time_entry.go index 1cc4203..161de3e 100644 --- a/timetask/time_entry.go +++ b/timetask/time_entry.go @@ -3,6 +3,7 @@ package timetask import "time" type TimeEntry struct { + PersonID int Client int Project int Module int @@ -13,3 +14,24 @@ type TimeEntry struct { Billable bool Description string } + +func NewTimeEntry( + profile Profile, + project Project, + date time.Time, + time int, + description string, +) TimeEntry { + return TimeEntry{ + PersonID: profile.PersonID, + Client: project.Client, + Project: project.Project, + Module: project.Module, + Task: project.Task, + WorkType: project.WorkType, + Date: date, + Time: time, + Billable: project.Billable, + Description: description, + } +} -- cgit v1.2.3 From 2bd0cb518e1eee9be503aea5198889253aa435f7 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 13:03:52 +0200 Subject: Project: Remove `Time` field Time spent on a project can be variable from day to day. The time shouldn't be stored on the project, and should no longer be passed in config.toml. Instead it should be a part of `TimeEntry`, which it now is. --- timetask/fields.go | 1 - 1 file changed, 1 deletion(-) diff --git a/timetask/fields.go b/timetask/fields.go index f535d92..9f7aa99 100644 --- a/timetask/fields.go +++ b/timetask/fields.go @@ -22,7 +22,6 @@ type Project struct { Module int Task int WorkType int `toml:"work_type"` - Time int Billable bool } -- cgit v1.2.3 From 84b921283c4106de55ca7908a58e8f1621b3841f Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 13:35:41 +0200 Subject: SubmitTimeEntry(): Remove `Profile` & `Project` arguments Now that `Profile` and `Project` have been subsumed into `TimeEntry` (f017c462593496efbc0810ec2603da49a2e3d9d8), these arguments should no longer be here and their data should come from `TimeEntry` instead. --- timetask/http.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/timetask/http.go b/timetask/http.go index 76bfdc3..4f52565 100644 --- a/timetask/http.go +++ b/timetask/http.go @@ -37,11 +37,9 @@ func Login(username, password string) (resp *http.Response, err error) { } func SubmitTimeEntry( - profile Profile, - project Project, time_entry TimeEntry, ) (resp *http.Response, err error) { - v := buildSubmissionParams(profile, time_entry) + v := buildSubmissionParams(time_entry) v.Set("module", "time") v.Set("action", "submitmultipletime") @@ -50,12 +48,12 @@ func SubmitTimeEntry( } -func buildSubmissionParams(profile Profile, time_entry TimeEntry) url.Values { +func buildSubmissionParams(time_entry TimeEntry) url.Values { v := url.Values{} v.Set( "f_personID0", - strconv.Itoa(profile.PersonID), + strconv.Itoa(time_entry.PersonID), ) v.Set( -- cgit v1.2.3 From 288da883a3a4a91fec67029b7695ec03099cfc46 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 14:16:29 +0200 Subject: Initial stab at submitting time entries for real main.go: * Login as the configured user (haven't yet handled making `PasswordCmd` an actual shell command) * Create a test time entry * Submit that time entry using `SubmitTimeEntry()` http.go: * Create a `baseURL` global that stores the base TimeTask URL to make requests to * Return an `http.Client` from `Login()` that can then be passed to `SubmitTimeEntry()` to reuse the login session. Needed to return a pointer to allow us to return `nil` from the first error handler in the function. Don't like that at all, but we're just trying to get it to work at this point. * Actually make an HTTP POST request in `SubmitTimeEntry()` using the given HTTP Client and existing time entry submission params * Take an `http.Client` argument in `SubmitTimeEntry()` to allow us to use a logged-in session to POST. Otherwise we'd be locked out. * Change `v` variable to `values` in `SubmitTimeEntry()` for better readability --- main.go | 23 +++++++++++++++++++++++ timetask/http.go | 35 +++++++++++++++++++++++++---------- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/main.go b/main.go index aea2112..1cc56c7 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( // "io/ioutil" "log" // "os" + "time" "github.com/teddywing/timetasker/timetask" @@ -25,6 +26,28 @@ var config Config func main() { loadConfig() + resp, client, err := timetask.Login( + config.Auth.Username, + config.Auth.PasswordCmd, + ) + if err != nil { + log.Fatalln(err) + } + log.Printf("%+v\n", resp) + + time_entry := timetask.NewTimeEntry( + config.Profile, + config.Projects["example"], + time.Now(), + 7, + "timetasker test", + ) + resp, err = timetask.SubmitTimeEntry(*client, time_entry) + if err != nil { + log.Fatalln(err) + } + log.Printf("%+v\n", resp) + // if len(os.Args) == 1 { // fmt.Println("Not enough arguments") // os.Exit(1) diff --git a/timetask/http.go b/timetask/http.go index 4f52565..cb91257 100644 --- a/timetask/http.go +++ b/timetask/http.go @@ -12,15 +12,21 @@ import ( "golang.org/x/net/publicsuffix" ) -func Login(username, password string) (resp *http.Response, err error) { +var baseURL string = "https://af83.timetask.com/index.php" + +func Login(username, password string) ( + resp *http.Response, + client *http.Client, + err error, +) { cookies, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) if err != nil { - return nil, err + return nil, nil, err } - client := http.Client{Jar: cookies} + client = &http.Client{Jar: cookies} resp, err = client.PostForm( - "https://af83.timetask.com/index.php", + baseURL, url.Values{ "module": {"people"}, "action": {"loginsubmit"}, @@ -30,21 +36,30 @@ func Login(username, password string) (resp *http.Response, err error) { }, ) if err != nil { - return resp, err + return resp, client, err } - return resp, err + return resp, client, err } func SubmitTimeEntry( + client http.Client, time_entry TimeEntry, ) (resp *http.Response, err error) { - v := buildSubmissionParams(time_entry) + values := buildSubmissionParams(time_entry) - v.Set("module", "time") - v.Set("action", "submitmultipletime") + values.Set("module", "time") + values.Set("action", "submitmultipletime") + + resp, err = client.PostForm( + baseURL, + values, + ) + if err != nil { + return resp, err + } - return nil, nil + return resp, nil } -- cgit v1.2.3 From bd2d890a9ad1128bf25b560fc4d796249c4ed495 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 14:34:13 +0200 Subject: main.go: Print HTTP response bodies for debugging Previously we were just printing the headers. Now print the bodies to allow us to inspect the result. Will probably want to add some handling that messages the user about authentication problems. --- main.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 1cc56c7..2f82643 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,7 @@ package main import ( // "fmt" - // "io/ioutil" + "io/ioutil" "log" // "os" "time" @@ -35,6 +35,10 @@ func main() { } log.Printf("%+v\n", resp) + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + log.Println(string(body)) + time_entry := timetask.NewTimeEntry( config.Profile, config.Projects["example"], @@ -48,6 +52,10 @@ func main() { } log.Printf("%+v\n", resp) + defer resp.Body.Close() + body, err = ioutil.ReadAll(resp.Body) + log.Println(string(body)) + // if len(os.Args) == 1 { // fmt.Println("Not enough arguments") // os.Exit(1) -- cgit v1.2.3 From 460ffe9ca5a7ad9ae5fd5a7d501b8cbd64e7646e Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 14:41:31 +0200 Subject: main.go: Add TOML tag to Config.PasswordCmd This field wasn't parsing correctly because of it's non-automatically-parseable format. --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 2f82643..3a343b5 100644 --- a/main.go +++ b/main.go @@ -15,7 +15,7 @@ import ( type Config struct { Auth struct { Username string - PasswordCmd string + PasswordCmd string `toml:"password_cmd"` } Profile timetask.Profile Projects map[string]timetask.Project -- cgit v1.2.3 From 24a3a2d9dbe6b2cd48d126f3f36a6d79497b4cc4 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sat, 3 Jun 2017 15:08:23 +0200 Subject: buildSubmissionParams(): Add `f_entryIndexes` param The param needs to be present in the request in order for it to be considered. Add it back in (we had it before 810b140b4a29b1159e76b51b90b9be7d22df1c3e) with only the `0` index being sent in the request. This is because we're only submitting a single time entry, the 0th one. (Other parameters end with a '0'.) --- timetask/http.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/timetask/http.go b/timetask/http.go index cb91257..736fcfb 100644 --- a/timetask/http.go +++ b/timetask/http.go @@ -123,5 +123,7 @@ func buildSubmissionParams(time_entry TimeEntry) url.Values { time_entry.Description, ) + v.Set("f_entryIndexes", "0") + return v } -- cgit v1.2.3