Initial commit: Null DRM Official
Capture, decrypt, and restream toolkit with compiled-in app modules (RTE, TG4, BBC), on-device MITM proxy, streamd control plane, and www. BBC module.yaml is published (clear streams); other module values stay local.
This commit is contained in:
commit
2fa8f2435f
121 changed files with 17802 additions and 0 deletions
128
apps/pkg/wvkey/wvkey.go
Normal file
128
apps/pkg/wvkey/wvkey.go
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
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"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue