Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix obtaining Pack URL #58

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 49 additions & 14 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
"fmt"
"os"
"path/filepath"
"strconv"
"math"

"regexp"

Expand Down Expand Up @@ -314,25 +316,58 @@ func (db *Database) getDeps(fileID int) ([]string, error) {
return result, nil
}

func (db *Database) getLatestPackURL(slug string) (string, error) {
func (db *Database) getLatestPackURL(slug string, fileID string) (string, error) {
// First try to find the pack by looking for the specific slug
pid, err := db.findProjectBySlug(slug, 1)
projectID, err := db.findProjectBySlug(slug, 1)
if err != nil {
return "", err
projectID, err = strconv.Atoi(slug)
if err != nil {
return "", fmt.Errorf("No modpack found %s", slug)
} else {
fmt.Printf("Interpretting %s as project ID\n", slug);
}
}


url := ""

if fileID != "" {
// Retrieve the JSON descriptor for this file so we can get the CDN url
descriptorUrl := fmt.Sprintf("https://addons-ecs.forgesvc.net/api/v2/addon/%d/file/%s", projectID, fileID)
descriptor, err := getJSONFromURL(descriptorUrl)
if err != nil {
return "", fmt.Errorf("failed to retrieve descriptor for %s: %+v", slug, err)
}

// Find the latest file given the project ID; we don't need to worry about matching the MC version,
// since modpacks are always locked to a specific version anyways
var fileID int
err = db.sqlDb.QueryRow("select fileid from files where projectid = ? order by tstamp desc limit 1", pid).Scan(&fileID)
switch {
case err == sql.ErrNoRows:
return "", fmt.Errorf("No modpack file found for %s", slug)
case err != nil:
return "", err
// Download the file to the pack mod directory
url = descriptor.Path("downloadUrl").Data().(string)
} else {
projectUrl := fmt.Sprintf("https://addons-ecs.forgesvc.net/api/v2/addon/%d", projectID)
project, err := getJSONFromURL(projectUrl)
if err != nil {
return "", fmt.Errorf("failed to retrieve project for %s: %+v", slug, err)
}

selectedFileType := math.MaxInt8

// Look for the file with most stable release type
files, _ := project.Path("latestFiles").Children()
for _, file := range files {
fileType, _ := intValue(file, "releaseType") // 1 = release, 2 = beta, 3 = alpha
fileUrl, _ := file.Path("downloadUrl").Data().(string)

// Prefer releases over beta/alpha
if fileType < selectedFileType {
selectedFileType = fileType
url = fileUrl
}
}

if url == "" {
return "", fmt.Errorf("Unable to find download URL for %s\n", slug)
}
}

// Construct a URL using the slug and file ID
return fmt.Sprintf("https://minecraft.curseforge.com/projects/%d/files/%d/download", pid, fileID), nil
return url, nil

}
26 changes: 15 additions & 11 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"path/filepath"
"regexp"
"sort"
"strings"
"time"

"github.com/xeonx/timeago"
Expand Down Expand Up @@ -67,9 +66,9 @@ var gCommands = map[string]command{
},
"pack.install": {
Fn: cmdPackInstall,
Desc: fmt.Sprintf("Install a mod pack, optionally using a URL to download. Use %s for the directory with a URL to use the name from the downloaded manifest", NamePlaceholder),
Desc: fmt.Sprintf("Install a mod pack, using either a manifest in the provided folder, or using slug or project ID.\nOptionally using a fileID to specify a specific version of the mod pack to download.\nUse %s for the directory with a slug/projectID to use the name from the downloaded manifest", NamePlaceholder),
ArgsCount: 1,
Args: "<directory/name> [<url>]",
Args: "<directory/name> [<slug/projectID> <fileID>]",
},
"info": {
Fn: cmdInfo,
Expand Down Expand Up @@ -149,7 +148,7 @@ func cmdPackCreate() error {
}

// Create a new pack directory
cp, err := NewModPack(dir, false, ARG_MMC)
cp, err := NewModPack(dir, 0, ARG_MMC)
if err != nil {
return err
}
Expand Down Expand Up @@ -180,22 +179,27 @@ func cmdPackCreate() error {

func cmdPackInstall() error {
dir := flag.Arg(1)
url := flag.Arg(2)
slug := flag.Arg(2)
fileID := flag.Arg(3)
url := ""

db, err := OpenDatabase()
if err != nil {
return err
}

if dir != "" && !strings.HasPrefix(url, "https://") {
url, err = db.getLatestPackURL(dir)
if slug != "" {
url, err = db.getLatestPackURL(slug, fileID)
if err != nil {
return err
}
}

// Only require a manifest if we're not installing from a URL
requireManifest := url == ""
requireManifest := 0
if url == "" {
requireManifest = 2
}

cp, err := NewModPack(dir, requireManifest, ARG_MMC)
if err != nil {
Expand Down Expand Up @@ -285,7 +289,7 @@ var curseForgeRegex = regexp.MustCompile("/projects/([\\w-]*)(/files/(\\d+))?")

func _modSelect(dir, modId, url string, clientOnly bool) error {
// Try to open the mod pack
cp, err := NewModPack(dir, true, ARG_MMC)
cp, err := NewModPack(dir, 1, ARG_MMC)
if err != nil {
return err
}
Expand Down Expand Up @@ -345,7 +349,7 @@ func cmdPackListLatest() error {
func cmdModUpdateAll() error {
dir := flag.Arg(1)

cp, err := NewModPack(dir, true, ARG_MMC)
cp, err := NewModPack(dir, 1, ARG_MMC)
if err != nil {
return err
}
Expand Down Expand Up @@ -378,7 +382,7 @@ func cmdServerInstall() error {

// Open the pack; we require the manifest and any
// config files to already be present
cp, err := NewModPack(dir, true, false)
cp, err := NewModPack(dir, 1, false)
if err != nil {
return err
}
Expand Down
19 changes: 14 additions & 5 deletions modpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,12 @@ func (pack *ModPack) fullName() string {
)
}

func NewModPack(dir string, requireManifest bool, enableMultiMC bool) (*ModPack, error) {
func NewModPack(dir string, TrequireManifest int, enableMultiMC bool) (*ModPack, error) {
pack := new(ModPack)
requireManifest := false;
if TrequireManifest > 0 {
requireManifest = true;
}

// Open a copy of the database for modpack related ops
db, err := OpenDatabase()
Expand Down Expand Up @@ -110,7 +114,11 @@ func NewModPack(dir string, requireManifest bool, enableMultiMC bool) (*ModPack,
// Try to load the manifest; only raise an error if we require it to be loaded
err = pack.loadManifest()
if requireManifest && err != nil {
return nil, err
if TrequireManifest == 2 {
return nil, fmt.Errorf("%v\nIf you meant to install a modpack identified by %[2]s run:\n\tmcdex pack.install %[2]s %[2]s\n", err, dir)
} else {
return nil, err
}
}

fmt.Printf("-- %s --\n", pack.gamePath())
Expand Down Expand Up @@ -157,10 +165,11 @@ func (pack *ModPack) download(url string) error {

fmt.Printf("Starting download of modpack: %s\n", url)

// This doesn't work any more.
// For the moment, we only support modpacks from Curseforge or FTB; check and enforce these conditions
if !hasAnyPrefix(url, VALID_URL_PREFIXES...) {
return fmt.Errorf("Invalid modpack URL; we only support Curseforge & feed-the-beast.com right now")
}
//if !hasAnyPrefix(url, VALID_URL_PREFIXES...) {
// return fmt.Errorf("Invalid modpack URL; we only support Curseforge & feed-the-beast.com right now")
//}

// Start the download
resp, err := HttpGet(url)
Expand Down