package spm import ( "bufio" "fmt" "io" "net/http" "os" "strings" ) const appIndexURL = "https://downloads.sourceforge.net/project/spitfire-browser/APPINDEX" func DownloadAppIndex(dest string) error { UpdateProgress(0, "Downloading APPINDEX") resp, err := http.Get(appIndexURL) if err != nil { return err } defer resp.Body.Close() out, err := os.Create(dest) if err != nil { return err } defer out.Close() totalSize := resp.ContentLength var downloaded int64 // Track progress as bytes are downloaded buf := make([]byte, 1024) for { n, err := resp.Body.Read(buf) if n > 0 { downloaded += int64(n) percentage := int(float64(downloaded) / float64(totalSize) * 100) UpdateProgress(percentage, "Downloading APPINDEX") if _, err := out.Write(buf[:n]); err != nil { return err } } if err == io.EOF { break } if err != nil { return err } } UpdateProgress(100, "APPINDEX downloaded") return nil } type AppIndexEntry struct { Name string Version string Release string // "nightly" / "stable" / etc. Arch string // e.g. "amd64", "386" OS string // e.g. "windows", "linux" Type string // "browser", "addon", "theme", etc. DownloadURL string } func ParseAppIndex(filePath string) ([]AppIndexEntry, error) { file, err := os.Open(filePath) if err != nil { return nil, err } defer file.Close() var entries []AppIndexEntry scanner := bufio.NewScanner(file) entry := AppIndexEntry{} for scanner.Scan() { line := scanner.Text() if strings.HasPrefix(line, "C:") { // Start of a new entry if entry.Name != "" { entries = append(entries, entry) entry = AppIndexEntry{} } } parts := strings.SplitN(line, ":", 2) if len(parts) < 2 { continue } key, value := parts[0], parts[1] switch key { case "P": entry.Name = value case "R": entry.Release = value case "V": entry.Version = value case "A": entry.Arch = value case "p": entry.OS = value case "d": entry.DownloadURL = value case "o": entry.Type = value } } // Append the last entry if any if entry.Name != "" { entries = append(entries, entry) } // Log all parsed entries fmt.Printf("[INFO] Total parsed entries: %d\n", len(entries)) for _, e := range entries { fmt.Printf(" - Name: %s, Release: %s, Type: %s, OS: %s, Arch: %s, Version: %s, URL: %s\n", e.Name, e.Release, e.Type, e.OS, e.Arch, e.Version, e.DownloadURL) } return entries, scanner.Err() }