diff --git a/internal/app/handler/download.go b/internal/app/handler/download.go index c276278..8eddb02 100644 --- a/internal/app/handler/download.go +++ b/internal/app/handler/download.go @@ -2,6 +2,7 @@ package handler import ( "context" + "errors" "fmt" "log/slog" "strings" @@ -13,8 +14,8 @@ import ( type DownloadHandler struct { handler - activationCode *lpac.ActivationCode - confirmDownload chan bool + activationCode *lpac.ActivationCode + downloadConfirmation chan bool } const ( @@ -24,7 +25,7 @@ const ( func HandleDownloadCommand(c telebot.Context) error { h := &DownloadHandler{ - confirmDownload: make(chan bool, 1), + downloadConfirmation: make(chan bool, 1), } h.init(c) h.state = h.stateManager.New(c) @@ -87,9 +88,13 @@ func (h *DownloadHandler) download(c telebot.Context) error { } timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) defer cancel() - if err := lpac.NewCmd(timeoutCtx, usbDevice).ProfileDownload(h.activationCode, func(current string, profileMetadata *lpac.Profile, confirmChan chan bool) error { - return h.handleDownloadProgress(c, message, current, profileMetadata, confirmChan) + if err := lpac.NewCmd(timeoutCtx, usbDevice).ProfileDownload(h.activationCode, func(current string, profileMetadata *lpac.Profile, downloadConfirmation chan bool) error { + return h.handleDownloadProgress(c, message, current, profileMetadata, downloadConfirmation) }); err != nil { + if errors.Is(err, lpac.ErrDownloadCancelled) { + _, err := c.Bot().Edit(message, "Download cancelled. /profiles") + return err + } slog.Info("failed to download profile", "error", err) _, err := c.Bot().Edit(message, "Failed to download profile: "+err.Error()) return err @@ -98,7 +103,7 @@ func (h *DownloadHandler) download(c telebot.Context) error { return err } -func (h *DownloadHandler) handleDownloadProgress(c telebot.Context, message *telebot.Message, current string, profileMetadata *lpac.Profile, confirmChan chan bool) error { +func (h *DownloadHandler) handleDownloadProgress(c telebot.Context, message *telebot.Message, current string, profileMetadata *lpac.Profile, downloadConfirmation chan bool) error { if profileMetadata != nil && current == lpac.ProgressMetadataParse { template := ` Are you sure you want to download the profile? @@ -111,7 +116,7 @@ ICCID: %s for _, action := range []string{"Yes", "No"} { btn := selector.Data(action, fmt.Sprint(time.Now().UnixNano()), action) c.Bot().Handle(&btn, func(c telebot.Context) error { - h.confirmDownload <- c.Callback().Data == "Yes" + h.downloadConfirmation <- c.Callback().Data == "Yes" return nil }) btns = append(btns, btn) @@ -120,15 +125,12 @@ ICCID: %s _, err := c.Bot().Edit(message, fmt.Sprintf(template, profileMetadata.ProviderName, profileMetadata.ProfileName, profileMetadata.ICCID), &selector) return err } + if current == lpac.ProgressPreviewConfirm { - if <-h.confirmDownload { - confirmChan <- true - return nil - } - confirmChan <- false - _, err := c.Bot().Edit(message, "Cancelled") - return err + downloadConfirmation <- <-h.downloadConfirmation + return nil } + _, err := c.Bot().Edit(message, current) return err } diff --git a/internal/pkg/lpac/cmd.go b/internal/pkg/lpac/cmd.go index 6d0be35..d852bf4 100644 --- a/internal/pkg/lpac/cmd.go +++ b/internal/pkg/lpac/cmd.go @@ -15,9 +15,7 @@ import ( "github.com/damonto/telegram-sms/internal/pkg/config" ) -var ( - ErrCanceled = errors.New("cancelled") -) +var ErrDownloadCancelled = errors.New("download cancelled") type Cmd struct { ctx context.Context @@ -64,7 +62,9 @@ func (c *Cmd) process(dst any, progress Progress) error { scanner.Split(bufio.ScanLines) var cmdErr error for scanner.Scan() { - if err := c.handleOutput(scanner.Text(), dst, progress); err != nil { + text := scanner.Text() + slog.Debug("lpac command output", "output", text) + if err := c.handleOutput(text, dst, progress); err != nil { cmdErr = err } } @@ -72,7 +72,6 @@ func (c *Cmd) process(dst any, progress Progress) error { } func (c *Cmd) handleOutput(output string, dst any, progress Progress) error { - slog.Debug("lpac output", "output", output) var commandOutput CommandOutput if err := json.Unmarshal([]byte(output), &commandOutput); err != nil { return err @@ -95,8 +94,8 @@ func (c *Cmd) handleLPAResponse(payload json.RawMessage, dst any) error { } if lpaPayload.Code != 0 { - if lpaPayload.Message == LPACancelled { - return nil + if lpaPayload.Message == LPADownloadCancelled { + return ErrDownloadCancelled } var errorMessage string if err := json.Unmarshal(lpaPayload.Data, &errorMessage); err != nil { @@ -107,6 +106,7 @@ func (c *Cmd) handleLPAResponse(payload json.RawMessage, dst any) error { } return errors.New(errorMessage) } + if dst != nil { return json.Unmarshal(lpaPayload.Data, dst) } @@ -128,17 +128,16 @@ func (c *Cmd) handleProgress(payload json.RawMessage, progress Progress) error { } if progressPayload.Message == ProgressPreviewConfirm { - confirmChan := make(chan bool, 1) - if err := progress(progressPayload.Message, nil, confirmChan); err != nil { + downloadConfirmation := make(chan bool, 1) + if err := progress(progressPayload.Message, nil, downloadConfirmation); err != nil { return err } - if <-confirmChan { + if <-downloadConfirmation { c.stdin.Write([]byte("y\n")) - return nil } else { c.stdin.Write([]byte("n\n")) - return ErrCanceled } + return nil } if text, ok := HumanReadableText[progressPayload.Message]; ok { diff --git a/internal/pkg/lpac/constant.go b/internal/pkg/lpac/constant.go index f452ff2..763fae6 100644 --- a/internal/pkg/lpac/constant.go +++ b/internal/pkg/lpac/constant.go @@ -14,7 +14,8 @@ const ( ProgressMetadataParse = "es8p_meatadata_parse" ProgressPreviewConfirm = "preview" - LPACancelled = "cancelled" + + LPADownloadCancelled = "cancelled" ) var HumanReadableText = map[string]string{ diff --git a/internal/pkg/lpac/type.go b/internal/pkg/lpac/type.go index b7b83ce..ca86046 100644 --- a/internal/pkg/lpac/type.go +++ b/internal/pkg/lpac/type.go @@ -2,7 +2,7 @@ package lpac import "encoding/json" -type Progress = func(current string, profileMetadata *Profile, confirmChan chan bool) error +type Progress = func(current string, profileMetadata *Profile, downloadConfirmation chan bool) error type CommandOutput struct { Type Command `json:"type"`