Linux mobile app for tracking and managing parcels.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
4.5 KiB

package main
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"time"
"github.com/alufers/inpost-cli/swagger"
"github.com/antihax/optional"
"github.com/mdp/qrterminal/v3"
"github.com/urfave/cli/v2"
"rsc.io/qr"
terminal "github.com/wayneashleyberry/terminal-dimensions"
)
var ParcelInfoCmd = &cli.Command{
Name: "parcel-info",
Aliases: []string{"qr", "info"},
Description: "Shows detailed information about a parcel, including a QR code",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "format",
Aliases: []string{"f"},
DefaultText: "text",
Value: "text",
Usage: "The output format: json or text (with a QR code)",
},
&cli.StringFlag{
Name: "qr",
Aliases: []string{"q"},
DefaultText: "H",
Value: "H",
Usage: "QR code quality settings: H, M, L, none (no QR code)",
},
},
Action: func(c *cli.Context) error {
var level *qr.Level
switch c.String("qr") {
case "L":
val := qr.L
level = &val
case "M":
val := qr.M
level = &val
case "H":
val := qr.H
level = &val
case "none":
default:
return fmt.Errorf("invalid --qr option, valid values are: L, M, H, none")
}
if err := refreshTokenIfNeeded(c.Context); err != nil {
return fmt.Errorf("failed to refresh token: %v", err)
}
cfg := swagger.NewConfiguration()
cfg.DefaultHeader["Authorization"] = "Bearer " + config.AuthToken
apiClient := swagger.NewAPIClient(cfg)
shipmentNumber, err := resolveShipmentNumber(c.Context, apiClient, c.Args().Get(0))
if err != nil {
return fmt.Errorf("failed to resolve shipment number: %w", err)
}
parcels, _, err := apiClient.DefaultApi.V1ParcelsGet(c.Context, &swagger.DefaultApiV1ParcelsGetOpts{
ShipmentNumbers: optional.NewString(shipmentNumber),
})
if err != nil {
return fmt.Errorf("failed to get parcels: %v", err)
}
if len(parcels) <= 0 {
return fmt.Errorf("No such parcel found")
}
p := parcels[0]
infoBuf := &bytes.Buffer{}
switch c.String("format") {
case "text":
fmt.Fprintf(infoBuf, "Shipment number: %v\n", p.ShipmentNumber)
fmt.Fprintf(infoBuf, "Sender name: %v\n", p.SenderName)
fmt.Fprintf(infoBuf, "Status: %v\n", p.Status)
fmt.Fprintf(infoBuf, "Recipient phone number: %v\n", p.PhoneNumber)
if p.OpenCode != "" {
fmt.Fprintf(infoBuf, "Open code: %v\n", p.OpenCode)
}
if !p.ExpiryDate.IsZero() {
fmt.Fprintf(infoBuf, "Expiry time: %v\n", formatDuration(p.ExpiryDate.Sub(time.Now())))
}
if p.PickupPoint != nil {
fmt.Fprintf(infoBuf, "Pickup point:\n")
if p.PickupPoint.AddressDetails != nil {
fmt.Fprintf(infoBuf, " Address: %v%v%v,\n",
p.PickupPoint.AddressDetails.Street,
prependSpaceIfNotEmpty(p.PickupPoint.AddressDetails.BuildingNumber),
prependSpaceIfNotEmpty(p.PickupPoint.AddressDetails.FlatNumber),
)
fmt.Fprintf(infoBuf, " City: %v, %v\n",
p.PickupPoint.AddressDetails.City,
p.PickupPoint.AddressDetails.Province,
)
fmt.Fprintf(infoBuf, " Location description: %v\n", p.PickupPoint.LocationDescription)
}
}
if p.OpenCode != "" {
fmt.Fprintf(infoBuf, "QR code URL: https://inpost.pl/%v/code/%v\n", p.PhoneNumber, p.OpenCode)
}
qrBuf := &bytes.Buffer{}
var qrWidth int
if p.QrCode != "" && level != nil {
qrterminal.GenerateWithConfig(p.QrCode, qrterminal.Config{
Level: *level,
Writer: qrBuf,
BlackChar: qrterminal.BLACK,
WhiteChar: qrterminal.WHITE,
QuietZone: 2,
}) // inpost uses HIGH error correction
code, err := qr.Encode(p.QrCode, *level)
if err == nil {
qrWidth = code.Size
}
}
qrLines := strings.Split(qrBuf.String(), "\n")
infoLines := strings.Split(infoBuf.String(), "\n")
var infoWidth int
for _, l := range infoLines {
if len(l) > infoWidth {
infoWidth = len(l)
}
}
termWidth, _ := terminal.Width()
if infoWidth+qrWidth+2 > int(termWidth) {
// print vertically
for _, line := range qrLines {
fmt.Println(line)
}
for _, line := range infoLines {
fmt.Println(line)
}
} else {
for i := 0; i < len(qrLines) || i < len(infoLines); i++ {
if i < len(qrLines) {
fmt.Print(qrLines[i])
}
if i < len(qrLines) && i < len(infoLines) {
fmt.Print(" ")
}
if i < len(infoLines) {
fmt.Print(infoLines[i])
}
fmt.Print("\n")
}
}
case "json":
s, _ := json.MarshalIndent(p, "", " ")
fmt.Print(string(s))
}
return nil
},
}