Add credential extraction registry for generate

Protocols like Xiaomi need credentials (tokens) in a separate top-level
YAML section, not in the stream URL itself. Introduce a registry pattern
mirroring streams.HandleFunc / tester.RegisterSource:

- pkg/generate/registry.go: ExtractFunc + RegisterExtract
- Extractors clean the URL (strip ?token=...) and return section/key/value
- writeCredentials emits sorted sections between go2rtc: and cameras:
- upsertCredentials in addToConfig merges into existing sections:
  * replaces value if key exists (token refresh)
  * inserts in sorted order if new
  * creates new top-level section before cameras: if missing

Xiaomi registers its extractor from internal/xiaomi/xiaomi.go. Adding
Tapo/Ring/Roborock later is one line + a small function in their
internal/*/ module -- zero changes in pkg/generate/.
This commit is contained in:
eduard256
2026-04-18 08:36:48 +00:00
parent 8294736bcb
commit 12780d7803
5 changed files with 271 additions and 4 deletions
+24
View File
@@ -15,6 +15,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/xiaomi/crypto"
"github.com/eduard256/strix/internal/api"
"github.com/eduard256/strix/internal/app"
"github.com/eduard256/strix/pkg/generate"
"github.com/eduard256/strix/pkg/tester"
"github.com/rs/zerolog"
)
@@ -53,6 +54,29 @@ func Init() {
})
api.HandleFunc("api/xiaomi", apiXiaomi)
generate.RegisterExtract("xiaomi", extractForConfig)
}
// extractForConfig strips ?token=... from xiaomi:// URL and returns
// userID + token for a top-level `xiaomi:` yaml section.
// ex. xiaomi://4161148305:cn@10.0.20.229?did=450924912&model=X&token=V1:...
// -> xiaomi://4161148305:cn@10.0.20.229?did=450924912&model=X, "xiaomi", "4161148305", "V1:..."
func extractForConfig(rawURL string) (cleaned, section, key, value string) {
u, err := url.Parse(rawURL)
if err != nil || u.User == nil {
return rawURL, "", "", ""
}
q := u.Query()
token := q.Get("token")
if token == "" {
return rawURL, "", "", ""
}
q.Del("token")
u.RawQuery = q.Encode()
return u.String(), "xiaomi", u.User.Username(), token
}
var log zerolog.Logger