Files
csgowtfd/csgo/sharecode.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
}