package wvkey import ( "bytes" "fmt" "os" "os/exec" "path/filepath" "strings" ) // Options for the Python wvkey.py helper. type Options struct { Python string // e.g. .venv/Scripts/python.exe Script string // path to wvkey.py WVD string PSSH string Auth string PID string LicenseURL string UserAgent string } // Fetch runs wvkey.py --quiet (ModularDrm) and returns the first KID:KEY line. func Fetch(opt Options) (string, error) { lines, err := run(opt, false, false) if err != nil { return "", err } if len(lines) == 0 { return "", fmt.Errorf("wvkey produced no KID:KEY") } return lines[0], nil } // FetchRaw runs wvkey.py --mode raw (Brightcove / octet-stream license). func FetchRaw(opt Options) (string, error) { lines, err := run(opt, true, false) if err != nil { return "", err } if len(lines) == 0 { return "", fmt.Errorf("wvkey produced no KID:KEY") } return lines[0], nil } // FetchRawAll returns every CONTENT key from a raw license response. func FetchRawAll(opt Options) ([]string, error) { return run(opt, true, true) } func run(opt Options, raw, all bool) ([]string, error) { py := opt.Python if py == "" { py = findPython() } script := opt.Script if script == "" { return nil, fmt.Errorf("wvkey script path required") } if strings.TrimSpace(opt.WVD) == "" { return nil, fmt.Errorf("wvkey --wvd path required") } if strings.TrimSpace(opt.PSSH) == "" { return nil, fmt.Errorf("wvkey --pssh required") } if strings.TrimSpace(opt.LicenseURL) == "" { return nil, fmt.Errorf("wvkey --license-url required") } args := []string{ script, "--wvd", opt.WVD, "--pssh", opt.PSSH, "--license-url", opt.LicenseURL, "--quiet", } if raw { args = append(args, "--mode", "raw") } else { args = append(args, "--mode", "modulardrm", "--auth", opt.Auth, "--pid", opt.PID) } if all { args = append(args, "--all") } if opt.UserAgent != "" { args = append(args, "--user-agent", opt.UserAgent) } cmd := exec.Command(py, args...) var stdout, stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr if err := cmd.Run(); err != nil { return nil, fmt.Errorf("wvkey failed: %w\n%s", err, strings.TrimSpace(stderr.String())) } var out []string for _, line := range strings.Split(strings.TrimSpace(stdout.String()), "\n") { line = strings.TrimSpace(line) if strings.Count(line, ":") == 1 && len(line) > 40 { out = append(out, line) } } if len(out) == 0 { return nil, fmt.Errorf("wvkey produced no KID:KEY (stderr=%s)", strings.TrimSpace(stderr.String())) } return out, nil } func findPython() string { candidates := []string{ filepath.Join(".venv", "Scripts", "python.exe"), filepath.Join(".venv", "bin", "python"), "python3", "python", } for _, c := range candidates { if filepath.IsAbs(c) || strings.Contains(c, string(os.PathSeparator)) { if st, err := os.Stat(c); err == nil && !st.IsDir() { return c } continue } if p, err := exec.LookPath(c); err == nil { return p } } return "python" }