1

There is no documentation on this.

I got as far as to understand that Murmur2 is used for hashing stuff (that is not mentioned anywhere either..)

But I don't exactly know how to hash the addon. Do I need to hash the filenames, the contents, what contents, all of them, in what order?

Can someone pls elaborate on a simple example addon like this?

_retail_/Interface/Addons/AutoRepair/

.rw-rw-r-- 2.3k marco  9 Mar 20:22 AutoRepair.lua
.rw-rw-r--  249 marco  9 Mar 20:22 AutoRepair.toc
.rw-rw-r--  371 marco  9 Mar 20:22 AutoRepair.xml

What needs to be done to get the fingerprint hash that I can send to the CF API to get the exact match for the mod?

My current approach was to hash the contents of the files, order these fingerprints asc, append them to a string in that order and hash that string to get the final fingerprint.

But that did not yield any success, when querying the API with that fingerprint.

Current Approach

package main

import (
    "bufio"
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "sort"
    "strconv"
    "strings"

    "github.com/joho/godotenv"
    mm "github.com/mistweaverco/go-murmur/murmur2"
)

func ReadFileAsBytes(path string) []byte {
    b, err := os.ReadFile(path)
    if err != nil {
        panic(err)
    }
    return b
}

func GetFileListRecursive(dir string) []string {
    files := []string{}
    fileInfos, err := ioutil.ReadDir(dir)
    if err != nil {
        log.Fatal(err)
    }
    for _, fileInfo := range fileInfos {
        if fileInfo.IsDir() {
            files = append(files, GetFileListRecursive(dir+fileInfo.Name()+"/")...)
        } else {
            files = append(files, dir+fileInfo.Name())
        }
    }
    return files
}

type Fingerprint struct {
    Title       string
    Hash        string
    Modified    int64
    AddonDir    string
    Fingerprint uint32
}

func GetFingerprint(addonDir string) Fingerprint {
    fingerprint := Fingerprint{}
    fingerprint.AddonDir = addonDir
    fullAddonDir := wowDirPrefix + "/Interface/Addons/" + addonDir + "/"
    toFingerprint := []string{}
    fingerprints := []uint32{}
    files := GetFileListRecursive(fullAddonDir)
    for _, file := range files {
        if strings.HasSuffix(file, ".lua") || strings.HasSuffix(file, ".toc") || strings.HasSuffix(file, ".xml") {
            toFingerprint = append(toFingerprint, file)
        }
    }
    sort.Strings(toFingerprint)
    fmt.Println(toFingerprint)
    for _, s := range toFingerprint {
        fc := ReadFileAsBytes(s)
        fingerprints = append(fingerprints, mm.MurmurHash2(fc, 1))
    }
    compositeFingerprint := ""
    sort.Slice(fingerprints, func(i, j int) bool { return fingerprints[i] < fingerprints[j] })
    fmt.Println(fingerprints)
    for _, f := range fingerprints {
        compositeFingerprint += strconv.Itoa(int(f))
    }

    fmt.Println(compositeFingerprint)
    fingerprint.Fingerprint = mm.MurmurHash2([]byte(compositeFingerprint), 1)
    return fingerprint
}

func env(k string, failOnMissing bool) string {
    value := os.Getenv(k)
    if value != "" {
        return value
    }
    if failOnMissing {
        log.Fatalf("%v environment variable is not set.", k)
    }
    return ""
}

func main() {
    godotenv.Load()

    wowDirPrefix = env("DEBUG_WOW_RETAIL_DIR", false)

    fp := GetFingerprint("AutoRepair")
    fmt.Println(fp)
}

The output of the program looks something like this:

[Interface/Addons/AutoRepair/AutoRepair.lua Interface/Addons/AutoRepair/AutoRepair.toc Interface/Addons/AutoRepair/AutoRepair.xml]
[1276060341 2556314513 2805448843]
127606034125563145132805448843
{  0 AutoRepair 1798771541}

With that output, the final computed fingerprint is 1798771541, but querying the API with that fingerprints yields no result, whereas it should yield the AutoRepair Addon.

Walialu
  • 4,096
  • 2
  • 27
  • 29

0 Answers0