117 lines
2.3 KiB
Go
117 lines
2.3 KiB
Go
package services
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net/url"
|
|
"path"
|
|
"strings"
|
|
|
|
"arma3-web-server/internal/models"
|
|
"golang.org/x/net/html"
|
|
)
|
|
|
|
func ParseModlistHTML(r io.Reader) (string, []models.ModEntry, error) {
|
|
doc, err := html.Parse(r)
|
|
if err != nil {
|
|
return "", nil, fmt.Errorf("parse html: %w", err)
|
|
}
|
|
|
|
var mods []models.ModEntry
|
|
seen := map[string]bool{}
|
|
|
|
var walk func(*html.Node)
|
|
walk = func(n *html.Node) {
|
|
if n.Type == html.ElementNode && n.Data == "tr" {
|
|
if name, id, ok := extractModRow(n); ok && id != "" {
|
|
if !seen[id] {
|
|
seen[id] = true
|
|
mods = append(mods, models.ModEntry{
|
|
ID: id,
|
|
Name: cleanModName(name),
|
|
Enabled: true,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
|
walk(c)
|
|
}
|
|
}
|
|
walk(doc)
|
|
|
|
if mods == nil {
|
|
mods = []models.ModEntry{}
|
|
}
|
|
return "", mods, nil
|
|
}
|
|
|
|
func extractModRow(tr *html.Node) (name, id string, ok bool) {
|
|
var cells []*html.Node
|
|
for c := tr.FirstChild; c != nil; c = c.NextSibling {
|
|
if c.Type == html.ElementNode && c.Data == "td" {
|
|
cells = append(cells, c)
|
|
}
|
|
}
|
|
if len(cells) < 3 {
|
|
return "", "", false
|
|
}
|
|
|
|
name = extractText(cells[0])
|
|
|
|
for c := cells[2].FirstChild; c != nil; c = c.NextSibling {
|
|
if c.Type == html.ElementNode && c.Data == "a" {
|
|
id = extractWorkshopID(c)
|
|
break
|
|
}
|
|
}
|
|
|
|
if name == "" {
|
|
return "", "", false
|
|
}
|
|
return name, id, true
|
|
}
|
|
|
|
func extractText(n *html.Node) string {
|
|
var b strings.Builder
|
|
var walk func(*html.Node)
|
|
walk = func(n *html.Node) {
|
|
if n.Type == html.TextNode {
|
|
b.WriteString(n.Data)
|
|
}
|
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
|
walk(c)
|
|
}
|
|
}
|
|
walk(n)
|
|
return strings.TrimSpace(b.String())
|
|
}
|
|
|
|
func extractWorkshopID(a *html.Node) string {
|
|
for _, attr := range a.Attr {
|
|
if attr.Key == "href" {
|
|
u, err := url.Parse(attr.Val)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
return u.Query().Get("id")
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func cleanModName(name string) string {
|
|
name = strings.TrimSpace(name)
|
|
name = strings.ReplaceAll(name, "/", "_")
|
|
name = strings.ReplaceAll(name, "\\", "_")
|
|
return name
|
|
}
|
|
|
|
func FileNameToModlistName(filename string) string {
|
|
ext := path.Ext(filename)
|
|
name := strings.TrimSuffix(filename, ext)
|
|
name = strings.ReplaceAll(name, "_", " ")
|
|
name = strings.ReplaceAll(name, "-", " ")
|
|
return name
|
|
}
|