You've already forked armbian-router
mirror of
https://github.com/armbian/armbian-router.git
synced 2026-01-06 10:37:03 -08:00
163 lines
3.9 KiB
Go
163 lines
3.9 KiB
Go
package redirector
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"net/url"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"golang.org/x/exp/maps"
|
|
"golang.org/x/text/cases"
|
|
"golang.org/x/text/language"
|
|
)
|
|
|
|
// ErrUnsupportedFormat is returned when an unsupported map format is used.
|
|
var ErrUnsupportedFormat = errors.New("unsupported map format")
|
|
var extensionFormats = []string{".asc", ".sha", ".torrent"}
|
|
|
|
// loadMapFile loads a file as a map
|
|
func loadMapFile(file string, specialExtensions map[string]string) (map[string]string, error) {
|
|
f, err := os.Open(file)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
ext := path.Ext(file)
|
|
|
|
switch ext {
|
|
case ".json":
|
|
return loadMapJSON(f, specialExtensions)
|
|
}
|
|
|
|
return nil, ErrUnsupportedFormat
|
|
}
|
|
|
|
// Map represents a JSON format of an asset list
|
|
type Map struct {
|
|
Assets []ReleaseFile `json:"assets"`
|
|
}
|
|
|
|
// ReleaseFile represents a file to be mapped
|
|
type ReleaseFile struct {
|
|
BoardSlug string `json:"board_slug"`
|
|
FileURL string `json:"file_url"`
|
|
FileURLASC string `json:"file_url_asc"`
|
|
FileURLSHA string `json:"file_url_sha"`
|
|
FileURLTorrent string `json:"file_url_torrent"`
|
|
FileUpdated string `json:"file_updated"`
|
|
FileSize string `json:"file_size"`
|
|
DistroRelease string `json:"distro"`
|
|
KernelBranch string `json:"branch"`
|
|
ImageVariant string `json:"variant"`
|
|
Preinstalled string `json:"file_application"`
|
|
Promoted string `json:"promoted"`
|
|
Repository string `json:"download_repository"`
|
|
Extension string `json:"file_extension"`
|
|
}
|
|
|
|
var distroCaser = cases.Title(language.Und)
|
|
|
|
// loadMapJSON loads a map file from JSON, based on the format specified in the github issue.
|
|
// See: https://github.com/armbian/os/pull/129
|
|
func loadMapJSON(f io.Reader, specialExtensions map[string]string) (map[string]string, error) {
|
|
// Avoid panics
|
|
if specialExtensions == nil {
|
|
specialExtensions = make(map[string]string)
|
|
}
|
|
|
|
m := make(map[string]string)
|
|
|
|
var data Map
|
|
|
|
if err := json.NewDecoder(f).Decode(&data); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, file := range data.Assets {
|
|
// Because download mapping a full URL, redirecting, and finding a server again is redundant,
|
|
// we parse the URL and only return the path here. Previously, it would use https://dl.armbian.com/PATH
|
|
// which is not supported, as the redirector will always prepend a server
|
|
u, err := url.Parse(file.FileURL)
|
|
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"error": err,
|
|
"uri": file.FileURL,
|
|
}).Warning("Error parsing redirect url or path")
|
|
continue
|
|
}
|
|
|
|
var sb strings.Builder
|
|
|
|
if file.Repository == "os" {
|
|
sb.WriteString("nightly/")
|
|
}
|
|
|
|
sb.WriteString(file.BoardSlug)
|
|
sb.WriteString("/")
|
|
sb.WriteString(distroCaser.String(file.DistroRelease))
|
|
sb.WriteString("_")
|
|
sb.WriteString(file.KernelBranch)
|
|
sb.WriteString("_")
|
|
sb.WriteString(file.ImageVariant)
|
|
|
|
if file.Preinstalled != "" {
|
|
sb.WriteString("-")
|
|
sb.WriteString(file.Preinstalled)
|
|
}
|
|
|
|
// Check special case for some extensions
|
|
for k, v := range specialExtensions {
|
|
if strings.Contains(file.Extension, k) {
|
|
sb.WriteString(v)
|
|
break
|
|
}
|
|
}
|
|
|
|
imageExtensions := maps.Keys(specialExtensions)
|
|
imageExtensions = append(imageExtensions, "img.xz") // extra allocation, but it's fine
|
|
|
|
// Add board into the map without an extension
|
|
for _, ext := range imageExtensions {
|
|
if strings.HasSuffix(file.Extension, ext) {
|
|
m[sb.String()] = u.Path
|
|
break
|
|
}
|
|
}
|
|
|
|
// Also add entries for .asc .sha and .torrent
|
|
for _, ext := range extensionFormats {
|
|
if strings.HasSuffix(file.Extension, ext) {
|
|
continue
|
|
}
|
|
|
|
var filePath string
|
|
switch ext {
|
|
case ".asc":
|
|
filePath = file.FileURLASC
|
|
case ".sha":
|
|
filePath = file.FileURLSHA
|
|
case ".torrent":
|
|
filePath = file.FileURLTorrent
|
|
}
|
|
|
|
m[sb.String()+ext] = filePath
|
|
}
|
|
|
|
sb.WriteString(".")
|
|
sb.WriteString(file.Extension)
|
|
|
|
m[sb.String()] = u.Path // Add board into the map with an extension
|
|
}
|
|
|
|
return m, nil
|
|
}
|