diff options
| -rw-r--r-- | main.go | 36 | ||||
| -rw-r--r-- | timetask/fields.go | 3 | ||||
| -rw-r--r-- | timetask/http.go | 206 | ||||
| -rw-r--r-- | timetask/profile.go | 5 | ||||
| -rw-r--r-- | timetask/time_entry.go | 63 | 
5 files changed, 161 insertions, 152 deletions
| @@ -2,9 +2,10 @@ package main  import (  	// "fmt" -	// "io/ioutil" +	"io/ioutil"  	"log"  	// "os" +	"time"  	"github.com/teddywing/timetasker/timetask" @@ -14,8 +15,9 @@ import (  type Config struct {  	Auth struct {  		Username    string -		PasswordCmd string +		PasswordCmd string `toml:"password_cmd"`  	} +	Profile timetask.Profile  	Projects map[string]timetask.Project  } @@ -24,6 +26,36 @@ 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) + +	defer resp.Body.Close() +	body, err := ioutil.ReadAll(resp.Body) +	log.Println(string(body)) + +	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) + +	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) diff --git a/timetask/fields.go b/timetask/fields.go index da2b37d..9f7aa99 100644 --- a/timetask/fields.go +++ b/timetask/fields.go @@ -21,8 +21,7 @@ type Project struct {  	Project  int  	Module   int  	Task     int -	WorkType int -	Time     int +	WorkType int `toml:"work_type"`  	Billable bool  } diff --git a/timetask/http.go b/timetask/http.go index 94a1597..736fcfb 100644 --- a/timetask/http.go +++ b/timetask/http.go @@ -6,21 +6,27 @@ import (  	"net/http"  	"net/http/cookiejar"  	"net/url" -	// "strconv" +	"strconv"  	// "strings"  	"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,112 +36,94 @@ func Login(username, password string) (resp *http.Response, err error) {  		},  	)  	if err != nil { +		return resp, client, err +	} + +	return resp, client, err +} + +func SubmitTimeEntry( +	client http.Client, +	time_entry TimeEntry, +) (resp *http.Response, err error) { +	values := buildSubmissionParams(time_entry) + +	values.Set("module", "time") +	values.Set("action", "submitmultipletime") + +	resp, err = client.PostForm( +		baseURL, +		values, +	) +	if err != nil {  		return resp, err  	} -	return resp, err +	return resp, nil  } -// 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 buildSubmissionParams(time_entry TimeEntry) url.Values { +	v := url.Values{} + +	v.Set( +		"f_personID0", +		strconv.Itoa(time_entry.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_billable0", +		billable, +	) + +	v.Set( +		"f_description0", +		time_entry.Description, +	) + +	v.Set("f_entryIndexes", "0") + +	return v +} diff --git a/timetask/profile.go b/timetask/profile.go new file mode 100644 index 0000000..9267ee6 --- /dev/null +++ b/timetask/profile.go @@ -0,0 +1,5 @@ +package timetask + +type Profile struct { +	PersonID int `toml:"person_id"` +} diff --git a/timetask/time_entry.go b/timetask/time_entry.go index 17a8e0c..161de3e 100644 --- a/timetask/time_entry.go +++ b/timetask/time_entry.go @@ -3,50 +3,35 @@ package timetask  import "time"  type TimeEntry struct { -	Client      string -	Project     string -	Module      string -	Task        string -	WorkType    string `yaml:"work_type"` +	PersonID    int +	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 +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,  	} - -	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  } | 
