50 lines
1.3 KiB
Go
50 lines
1.3 KiB
Go
package csgo
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"math/big"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
//goland:noinspection SpellCheckingInspection
|
|
var DICT = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefhijkmnopqrstuvwxyz23456789"
|
|
var sharecodeRexEx = regexp.MustCompile(`^CSGO(?:-?\w{5}){5}$`)
|
|
|
|
func DecodeSharecode(code string) (matchID, outcomeID uint64, tokenID uint16, err error) {
|
|
if !sharecodeRexEx.MatchString(code) {
|
|
return 0, 0, 0, fmt.Errorf("not a CSGO sharecode: %s", code)
|
|
}
|
|
|
|
cleanCode := strings.ReplaceAll(strings.ReplaceAll(code, "CSGO", ""), "-", "")
|
|
|
|
chars := ReverseString(strings.Split(cleanCode, ""))
|
|
bigInt := new(big.Int)
|
|
dictLenBig := big.NewInt(int64(len(DICT)))
|
|
|
|
for _, c := range chars {
|
|
bigInt.Mul(bigInt, dictLenBig)
|
|
bigInt.Add(bigInt, big.NewInt(int64(strings.Index(DICT, c))))
|
|
}
|
|
|
|
if bigInt.BitLen() > 144 { //nolint:gomnd
|
|
return 0, 0, 0, fmt.Errorf("invalid sharecode")
|
|
}
|
|
bytes := make([]byte, 18) //nolint:gomnd
|
|
bigInt.FillBytes(bytes)
|
|
|
|
matchID = binary.LittleEndian.Uint64(bytes[0:8])
|
|
outcomeID = binary.LittleEndian.Uint64(bytes[8:16])
|
|
tokenID = binary.LittleEndian.Uint16(bytes[16:18])
|
|
|
|
return
|
|
}
|
|
|
|
func ReverseString(numbers []string) []string {
|
|
for i, j := 0, len(numbers)-1; i < j; i, j = i+1, j-1 {
|
|
numbers[i], numbers[j] = numbers[j], numbers[i]
|
|
}
|
|
return numbers
|
|
}
|