factor error and cleanup

This commit is contained in:
celogeek 2022-05-14 17:47:23 +02:00
parent fff782569f
commit 2d1fdc1314
Signed by: celogeek
GPG Key ID: E6B7BDCFC446233A
4 changed files with 34 additions and 199 deletions

View File

@ -0,0 +1,18 @@
package main
import (
"fmt"
"strings"
)
type ResponseError struct {
Err string `json:"error"`
Details []string `json:"details"`
}
func (u *ResponseError) Error() string {
if len(u.Details) == 0 {
return u.Err
}
return fmt.Sprintf("%s: \n - %s", u.Err, strings.Join(u.Details, "\n - "))
}

View File

@ -1,7 +1,6 @@
package main
import (
"errors"
"fmt"
"github.com/go-resty/resty/v2"
@ -18,10 +17,6 @@ type LoginRequest struct {
Password string `json:"password"`
}
type LoginError struct {
Error string
}
type LoginResponse struct {
Token string
}
@ -35,16 +30,16 @@ func (c *LoginCommand) Execute(args []string) error {
R().
SetBody(&LoginRequest{c.Login, c.Password}).
SetResult(&LoginResponse{}).
SetError(&LoginError{}).
SetError(&ResponseError{}).
Post("/account/login")
if err != nil {
return err
}
if err, ok := resp.Error().(*LoginError); ok {
if resp.IsError() {
logger.Printf("Login failed!")
return errors.New(err.Error)
return resp.Error().(*ResponseError)
}
logger.Println("Login succeed!")

View File

@ -1,8 +1,6 @@
package main
import (
"errors"
"github.com/go-resty/resty/v2"
)
@ -17,13 +15,6 @@ type RegisterRequest struct {
Password string `json:"password"`
}
type RegisterResponse struct {
}
type RegisterError struct {
Error string
}
func (c *RegisterCommand) Execute(args []string) error {
logger.Printf("Registering on %s...\n", c.Url)
@ -31,18 +22,17 @@ func (c *RegisterCommand) Execute(args []string) error {
resp, err := cli.
R().
SetError(&ResponseError{}).
SetBody(&RegisterRequest{c.Login, c.Password}).
SetResult(&RegisterResponse{}).
SetError(&RegisterError{}).
Post("/account/signup")
if err != nil {
return err
}
if err, ok := resp.Error().(*RegisterError); ok {
if resp.IsError() {
logger.Println("Registering failed!")
return errors.New(err.Error)
return resp.Error().(*ResponseError)
}
logger.Println("Registering succeed!")

View File

@ -1,16 +1,12 @@
package main
import (
"crypto/sha1"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"sync"
"github.com/go-resty/resty/v2"
"github.com/schollz/progressbar/v3"
@ -24,18 +20,6 @@ type UploadCommand struct {
Workers uint32 `short:"w" long:"workers" description:"Number of workers for uploading chunks" default:"4"`
}
type UploadError struct {
Err string `json:"error"`
Details []string `json:"details"`
}
func (u *UploadError) Error() string {
if len(u.Details) == 0 {
return u.Err
}
return fmt.Sprintf("%s: \n - %s", u.Err, strings.Join(u.Details, "\n - "))
}
type UploadCreate struct {
UploadId string `json:"upload_id"`
}
@ -47,171 +31,19 @@ type UploadPartResult struct {
PartSha256 string `json:"sha256"`
}
type UploadCompleteRequest struct {
Sha256 string `json:"sha256" binding:"required,sha256"`
Name string `json:"name" binding:"required"`
Parts uint `json:"parts" binding:"required"`
}
type UploadFileRequest struct {
Name string
Checksum string
Chunks []string
}
type UploadFileResponse struct {
Sum string
NbChunks uint32
Size uint64
}
func (c *UploadCommand) Cli() *resty.Client {
return resty.New().SetBaseURL(c.Url).SetAuthScheme("Private").SetAuthToken(c.Token)
}
func (c *UploadCommand) FileExists() (string, error) {
f, err := os.Open(c.File)
if err != nil {
return "", err
}
defer f.Close()
st, err := f.Stat()
if err != nil {
return "", err
}
progress := progressbar.DefaultBytes(st.Size(), fmt.Sprintf("Checking %s", filepath.Base(c.File)))
defer progress.Close()
tee := io.TeeReader(f, progress)
checksum := sha1.New()
io.Copy(checksum, tee)
sum := hex.EncodeToString(checksum.Sum(nil))
resp, err := c.Cli().R().Head(fmt.Sprintf("/file/%s", sum))
if err != nil {
return "", err
}
if resp.IsSuccess() {
return "", errors.New("file already exists")
}
return sum, nil
}
func (c *UploadCommand) FileUpload(sum string) error {
f, err := os.Open(c.File)
if err != nil {
return err
}
defer f.Close()
st, err := f.Stat()
if err != nil {
return err
}
nbChunks := st.Size() / photosapi.CHUNK_SIZE
if st.Size()%photosapi.CHUNK_SIZE > 0 {
nbChunks++
}
uploadFile := &UploadFileRequest{
Name: filepath.Base(c.File),
Chunks: make([]string, nbChunks),
Checksum: sum,
}
cli := c.Cli()
progress := progressbar.DefaultBytes(st.Size(), fmt.Sprintf("Uploading %s", uploadFile.Name))
defer progress.Close()
wg := sync.WaitGroup{}
mu := sync.Mutex{}
wg.Add(4)
wgErrors := make([]error, c.Workers)
i := int64(0)
for w := uint32(0); w < c.Workers; w++ {
go func(w uint32) {
defer wg.Done()
b := make([]byte, photosapi.CHUNK_SIZE)
for {
mu.Lock()
part := i
i++
n, err := f.Read(b)
mu.Unlock()
if n == 0 {
if err == io.EOF {
break
}
wgErrors[w] = err
return
}
checksum := sha1.New()
checksum.Write(b[0:n])
sum := hex.EncodeToString(checksum.Sum(nil))
resp, err := cli.R().Head(fmt.Sprintf("/file/chunk/%s", sum))
if err != nil {
wgErrors[w] = err
return
}
if resp.IsSuccess() {
uploadFile.Chunks[part] = sum
progress.Add(n)
continue
}
resp, err = cli.R().SetError(&UploadError{}).SetBody(b[0:n]).Post("/file/chunk")
if err != nil {
wgErrors[w] = err
return
}
if err, ok := resp.Error().(*UploadError); ok {
wgErrors[w] = err
return
}
uploadFile.Chunks[part] = sum
progress.Add(n)
}
}(w)
}
wg.Wait()
for _, err := range wgErrors {
if err != nil {
return err
}
}
resp, err := cli.R().SetBody(uploadFile).SetError(&UploadError{}).SetResult(&UploadFileResponse{}).Post("/file")
if err != nil {
return err
}
if err, ok := resp.Error().(*UploadError); ok {
logger.Println("Upload failed")
return err
}
if result, ok := resp.Result().(*UploadFileResponse); ok {
fmt.Printf("Upload succeed\nSum: %s\nNbChunks: %d\nSize: %d\n", result.Sum, result.NbChunks, result.Size)
}
return nil
}
func (c *UploadCommand) Execute(args []string) error {
cli := c.Cli()
resp, err := cli.R().SetError(&UploadError{}).SetResult(&UploadCreate{}).Post("/upload")
resp, err := cli.R().SetError(&ResponseError{}).SetResult(&UploadCreate{}).Post("/upload")
if err != nil {
return err
}
if err, ok := resp.Error().(*UploadError); ok {
return err
if resp.IsError() {
return resp.Error().(*ResponseError)
}
uploadId := resp.Result().(*UploadCreate).UploadId
@ -249,7 +81,7 @@ func (c *UploadCommand) Execute(args []string) error {
resp, err := cli.
R().
SetError(&UploadError{}).
SetError(&ResponseError{}).
SetResult(&UploadPartResult{}).
SetQueryParam("part", fmt.Sprint(parts)).
SetQueryParam("sha256", hex.EncodeToString(partsha256.Sum(nil))).
@ -261,8 +93,8 @@ func (c *UploadCommand) Execute(args []string) error {
return err
}
if err, ok := resp.Error().(*UploadError); ok {
return err
if resp.IsError() {
return resp.Error().(*ResponseError)
}
}
@ -274,9 +106,9 @@ func (c *UploadCommand) Execute(args []string) error {
resp, err = cli.
R().
SetError(&UploadError{}).
SetError(&ResponseError{}).
SetPathParam("id", uploadId).
SetBody(&UploadCompleteRequest{
SetBody(&photosapi.UploadCompleteRequest{
Sha256: hex.EncodeToString(completesha256.Sum(nil)),
Parts: uint(parts),
Name: filepath.Base(c.File),
@ -287,8 +119,8 @@ func (c *UploadCommand) Execute(args []string) error {
return err
}
if err, ok := resp.Error().(*UploadError); ok {
return err
if resp.IsError() {
return resp.Error().(*ResponseError)
}
fmt.Printf("Response: %s\n", resp.Body())