Skip to content

Commit 169af4b

Browse files
authored
Add ability to download .ipa by the app ID (#263)
* Add ability to download .ipa by the app ID * Update `download` command usage in README * Fix the linter warnings
1 parent f68a119 commit 169af4b

File tree

3 files changed

+39
-15
lines changed

3 files changed

+39
-15
lines changed

README.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,17 @@ Usage:
107107
ipatool download [flags]
108108
109109
Flags:
110-
-b, --bundle-identifier string The bundle identifier of the target iOS app (required)
110+
-i, --app-id int ID of the target iOS app (required)
111+
-b, --bundle-identifier string The bundle identifier of the target iOS app (overrides the app ID)
111112
-h, --help help for download
112113
-o, --output string The destination path of the downloaded app package
113114
--purchase Obtain a license for the app if needed
114115
115116
Global Flags:
116-
--format format sets output format for command; can be 'text', 'json' (default text)
117-
--non-interactive run in non-interactive session
118-
--verbose enables verbose logs
117+
--format format sets output format for command; can be 'text', 'json' (default text)
118+
--keychain-passphrase string passphrase for unlocking keychain
119+
--non-interactive run in non-interactive session
120+
--verbose enables verbose logs
119121
```
120122

121123
**Note:** the tool runs in interactive mode by default. Use the `--non-interactive` flag

cmd/download.go

+17-7
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,18 @@ func downloadCmd() *cobra.Command {
1616
var (
1717
acquireLicense bool
1818
outputPath string
19+
appID int64
1920
bundleID string
2021
)
2122

2223
cmd := &cobra.Command{
2324
Use: "download",
2425
Short: "Download (encrypted) iOS app packages from the App Store",
2526
RunE: func(cmd *cobra.Command, args []string) error {
27+
if appID == 0 && bundleID == "" {
28+
return errors.New("either the app ID or the bundle identifier must be specified")
29+
}
30+
2631
var lastErr error
2732
var acc appstore.Account
2833

@@ -43,13 +48,18 @@ func downloadCmd() *cobra.Command {
4348
acc = loginResult.Account
4449
}
4550

46-
lookupResult, err := dependencies.AppStore.Lookup(appstore.LookupInput{Account: acc, BundleID: bundleID})
47-
if err != nil {
48-
return err
51+
app := appstore.App{ID: appID}
52+
if bundleID != "" {
53+
lookupResult, err := dependencies.AppStore.Lookup(appstore.LookupInput{Account: acc, BundleID: bundleID})
54+
if err != nil {
55+
return err
56+
}
57+
58+
app = lookupResult.App
4959
}
5060

5161
if errors.Is(lastErr, appstore.ErrLicenseRequired) {
52-
err := dependencies.AppStore.Purchase(appstore.PurchaseInput{Account: acc, App: lookupResult.App})
62+
err := dependencies.AppStore.Purchase(appstore.PurchaseInput{Account: acc, App: app})
5363
if err != nil {
5464
return err
5565
}
@@ -74,7 +84,7 @@ func downloadCmd() *cobra.Command {
7484
)
7585
}
7686

77-
out, err := dependencies.AppStore.Download(appstore.DownloadInput{Account: acc, App: lookupResult.App, OutputPath: outputPath, Progress: progress})
87+
out, err := dependencies.AppStore.Download(appstore.DownloadInput{Account: acc, App: app, OutputPath: outputPath, Progress: progress})
7888
if err != nil {
7989
return err
8090
}
@@ -112,10 +122,10 @@ func downloadCmd() *cobra.Command {
112122
},
113123
}
114124

115-
cmd.Flags().StringVarP(&bundleID, "bundle-identifier", "b", "", "The bundle identifier of the target iOS app (required)")
125+
cmd.Flags().Int64VarP(&appID, "app-id", "i", 0, "ID of the target iOS app (required)")
126+
cmd.Flags().StringVarP(&bundleID, "bundle-identifier", "b", "", "The bundle identifier of the target iOS app (overrides the app ID)")
116127
cmd.Flags().StringVarP(&outputPath, "output", "o", "", "The destination path of the downloaded app package")
117128
cmd.Flags().BoolVar(&acquireLicense, "purchase", false, "Obtain a license for the app if needed")
118-
_ = cmd.MarkFlagRequired("bundle-identifier")
119129

120130
return cmd
121131
}

pkg/appstore/appstore_download.go

+16-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"io"
88
"os"
9+
"strconv"
910
"strings"
1011

1112
"github.com/majd/ipatool/v2/pkg/http"
@@ -161,10 +162,21 @@ func (*appstore) downloadRequest(acc Account, app App, guid string) http.Request
161162
}
162163

163164
func fileName(app App) string {
164-
return fmt.Sprintf("%s_%d_%s.ipa",
165-
app.BundleID,
166-
app.ID,
167-
app.Version)
165+
var parts []string
166+
167+
if app.BundleID != "" {
168+
parts = append(parts, app.BundleID)
169+
}
170+
171+
if app.ID != 0 {
172+
parts = append(parts, strconv.FormatInt(app.ID, 10))
173+
}
174+
175+
if app.Version != "" {
176+
parts = append(parts, app.Version)
177+
}
178+
179+
return fmt.Sprintf("%s.ipa", strings.Join(parts, "_"))
168180
}
169181

170182
func (t *appstore) resolveDestinationPath(app App, path string) (string, error) {

0 commit comments

Comments
 (0)