-
Notifications
You must be signed in to change notification settings - Fork 0
/
data.go
112 lines (90 loc) · 2.66 KB
/
data.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package utils
import (
"fmt"
"regexp"
"strconv"
"strings"
"unicode"
"github.com/breadinator/swkshp/errors"
"golang.org/x/exp/constraints"
"golang.org/x/text/runes"
"golang.org/x/text/transform"
"golang.org/x/text/unicode/norm"
)
/* STRING HANDLING */
const workshop string = `https://steamcommunity.com/workshop/filedetails/?id=%s`
// Converts a Workshop ID to a Workshop URL
func WorkshopIDToURL(id any) (string, bool) {
var idStr string
switch t := id.(type) {
case int:
idStr = strconv.Itoa(t)
case string:
idStr = t
default:
return "", false
}
return fmt.Sprintf(workshop, idStr), true
}
var (
illegalChars = regexp.MustCompile(`[^a-zA-Z0-9_]`) // Anything other than either case a-z, arabic numerals or underscores
wspace = regexp.MustCompile(`\s`) // Any whitespace
)
// Replaces accents (e.g. 'é' -> 'e'). Converts to lowercase. Replaces whitespace with underscores. Removes all illegal characters.
func Sanitise[S ~string](str S) (string, error) {
// Transform accents
t := transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC)
s, _, err := transform.String(t, string(str))
// Lower case
s = strings.ToLower(s) // can maybe merge to above
// Whitespace
s = wspace.ReplaceAllString(s, "_")
// Remove illegal characters
s = illegalChars.ReplaceAllString(s, "")
return s, err
}
// Regular expression to get the ID from a URL.
var getIDRegexp = regexp.MustCompile(`\?id=(\d+)`) // stricter: `steamcommunity\.com\/(?:workshop|sharedfiles)\/filedetails\/\?id=(\d+)`
// Extracts the Workshop ID from its URL.
func WorkshopIDFromURL(url string) (int, error) {
matches := getIDRegexp.FindStringSubmatch(url)
if len(matches) <= 1 {
return 0, errors.ErrParsingFailed
}
return strconv.Atoi(matches[1])
}
/* SLICES DATA HANDLING */
// Checks if the items and order of two slices are equal
func SlicesEqual[T constraints.Ordered](a, b []T) bool {
if len(a) != len(b) {
return false
}
for i, item := range a {
if b[i] != item {
return false
}
}
return true
}
// Checks if a slice of strings contains an given string.
func In[T comparable](slice []T, item T) bool {
for _, a := range slice {
if item == a {
return true
}
}
return false
}
/* INT HANDLING */
// Pass in any non-zero number of orderables and get back the one that's "smallest" (i.e. it < the rest).
//
// Uses args `a` and `numbers` to ensure at least one value is given.
func Min[T constraints.Ordered](a T, numbers ...T) T {
smallest := a
for _, n := range numbers {
if n < smallest {
smallest = n
}
}
return smallest
}