This commit is contained in:
@@ -25,14 +25,14 @@ func (i invoiceReq) GetRepos() (repos []invoice.Repo, err error) {
|
||||
parts := strings.Split(repo, "/")
|
||||
if len(parts) != 2 {
|
||||
err = fmt.Errorf("cannot read body: repo with index %d does not split into 2 parts", i)
|
||||
return
|
||||
return repos, err
|
||||
}
|
||||
repos = append(repos, invoice.Repo{
|
||||
Owner: parts[0],
|
||||
Repo: parts[1],
|
||||
})
|
||||
}
|
||||
return
|
||||
return repos, err
|
||||
}
|
||||
|
||||
type sendReq struct {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"git.schreifuchs.ch/lou-taylor/accounting/internal/api/httpinvoce"
|
||||
"git.schreifuchs.ch/lou-taylor/accounting/internal/config"
|
||||
"git.schreifuchs.ch/lou-taylor/accounting/internal/email"
|
||||
"git.schreifuchs.ch/lou-taylor/accounting/pdf"
|
||||
"git.schreifuchs.ch/lou-taylor/accounting/internal/pdf"
|
||||
"git.schreifuchs.ch/lou-taylor/accounting/pkg/invoice"
|
||||
)
|
||||
|
||||
|
||||
93
internal/ask/ask.go
Normal file
93
internal/ask/ask.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package ask
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func raw[T any](query string, to byte, validate func(string) (v T, msg string)) T {
|
||||
fmt.Println(query)
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
for {
|
||||
text, _ := reader.ReadString(to)
|
||||
v, msg := validate(strings.TrimSpace(text[:len(text)-1]))
|
||||
|
||||
if msg == "" {
|
||||
return v
|
||||
}
|
||||
fmt.Println(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func String(query string, min, max int) string {
|
||||
return raw(query, '\n', func(s string) (v string, msg string) {
|
||||
v = s
|
||||
|
||||
if min >= 0 && len(v) < min {
|
||||
msg = fmt.Sprintf("your input is to short. Minimum length is %d", min)
|
||||
return v, msg
|
||||
}
|
||||
if max >= 0 && len(v) > max {
|
||||
msg = fmt.Sprintf("your input is to long. Maximum length is %d", min)
|
||||
return v, msg
|
||||
}
|
||||
return v, msg
|
||||
})
|
||||
}
|
||||
|
||||
func StringSlice(query string, min, max, smin, smax int) []string {
|
||||
return raw(query, ';', func(s string) (v []string, msg string) {
|
||||
splits := strings.Split(s, ",")
|
||||
v = make([]string, 0, len(splits))
|
||||
for _, split := range splits {
|
||||
v = append(v, strings.TrimSpace(split))
|
||||
}
|
||||
|
||||
if min >= 0 && len(v) < min {
|
||||
msg = fmt.Sprintf("your input is to short. Minimum length is %d", min)
|
||||
}
|
||||
if max >= 0 && len(v) > max {
|
||||
msg = fmt.Sprintf("your input is to long. Maximum length is %d", max)
|
||||
}
|
||||
for i, s := range v {
|
||||
if smin >= 0 && len(s) < smin {
|
||||
msg = fmt.Sprintf("your is value at index %d is to short. Minimum length is %d", i, smin)
|
||||
}
|
||||
if smax >= 0 && len(s) > smax {
|
||||
msg = fmt.Sprintf("your is value at index %d is to long. Maximum length is %d", i, smax)
|
||||
}
|
||||
}
|
||||
|
||||
return v, msg
|
||||
})
|
||||
}
|
||||
|
||||
func Boolean(query string, def bool) bool {
|
||||
if def {
|
||||
query += " (Y/n)"
|
||||
} else {
|
||||
query += " (y/N)"
|
||||
}
|
||||
return raw(query, '\n', func(s string) (v bool, msg string) {
|
||||
s = strings.ToLower(s)
|
||||
|
||||
if s == "" {
|
||||
v = def
|
||||
return v, msg
|
||||
}
|
||||
|
||||
if s == "y" {
|
||||
v = true
|
||||
return v, msg
|
||||
}
|
||||
if s == "n" {
|
||||
v = false
|
||||
return v, msg
|
||||
}
|
||||
|
||||
msg = `your answer must be "y" "n" or enter for default`
|
||||
return v, msg
|
||||
})
|
||||
}
|
||||
25
internal/ask/duration.go
Normal file
25
internal/ask/duration.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package ask
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Duration(query string, min, max time.Duration) time.Duration {
|
||||
return raw(query, '\n', func(s string) (v time.Duration, msg string) {
|
||||
v, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
msg = "please enter a number"
|
||||
return v, msg
|
||||
}
|
||||
if min >= 0 && v < min {
|
||||
msg = fmt.Sprintf("your number must be bigger than %d", min)
|
||||
return v, msg
|
||||
}
|
||||
if max >= 0 && v > max {
|
||||
msg = fmt.Sprintf("your number must be smaller than %d", min)
|
||||
return v, msg
|
||||
}
|
||||
return v, msg
|
||||
})
|
||||
}
|
||||
44
internal/ask/number.go
Normal file
44
internal/ask/number.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package ask
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func Int(query string, min, max int) int {
|
||||
return raw(query, '\n', func(s string) (v int, msg string) {
|
||||
v, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
msg = "please enter a number"
|
||||
return v, msg
|
||||
}
|
||||
if min >= 0 && v < min {
|
||||
msg = fmt.Sprintf("your number must be bigger than %d", min)
|
||||
return v, msg
|
||||
}
|
||||
if max >= 0 && v > max {
|
||||
msg = fmt.Sprintf("your number must be smaller than %d", max)
|
||||
return v, msg
|
||||
}
|
||||
return v, msg
|
||||
})
|
||||
}
|
||||
|
||||
func Float64(query string, min, max float64) float64 {
|
||||
return raw(query, '\n', func(s string) (v float64, msg string) {
|
||||
v, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
msg = "please enter a number"
|
||||
return v, msg
|
||||
}
|
||||
if min >= 0 && v < min {
|
||||
msg = fmt.Sprintf("your number must be bigger than %g", min)
|
||||
return v, msg
|
||||
}
|
||||
if max >= 0 && v > max {
|
||||
msg = fmt.Sprintf("your number must be smaller than %g", max)
|
||||
return v, msg
|
||||
}
|
||||
return v, msg
|
||||
})
|
||||
}
|
||||
42
internal/pdf/resource.go
Normal file
42
internal/pdf/resource.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package pdf
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/starwalkn/gotenberg-go-client/v8"
|
||||
"github.com/starwalkn/gotenberg-go-client/v8/document"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
gotenberg *gotenberg.Client
|
||||
}
|
||||
|
||||
func New(hostname string) (service *Service, err error) {
|
||||
service = &Service{}
|
||||
service.gotenberg, err = gotenberg.NewClient(hostname, http.DefaultClient)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) HtmlToPdf(html string) (pdf io.ReadCloser, err error) {
|
||||
index, err := document.FromString("index.html", html)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
req := gotenberg.NewHTMLRequest(index)
|
||||
req.PaperSize(gotenberg.A4)
|
||||
|
||||
req.Margins(gotenberg.NoMargins)
|
||||
// Skips the IDLE events for faster PDF conversion.
|
||||
req.SkipNetworkIdleEvent(true)
|
||||
req.EmulatePrintMediaType()
|
||||
|
||||
resp, err := s.gotenberg.Send(context.Background(), req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
pdf = resp.Body
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user