252 lines
8.7 KiB
Go
252 lines
8.7 KiB
Go
package main
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"encoding/json"
|
||
|
|
"flag"
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
"net/http"
|
||
|
|
"net/url"
|
||
|
|
"os"
|
||
|
|
"strings"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
volcbase "github.com/volcengine/volc-sdk-golang/base"
|
||
|
|
)
|
||
|
|
|
||
|
|
type responseEnvelope struct {
|
||
|
|
ResponseMetadata struct {
|
||
|
|
Error *struct {
|
||
|
|
Code string `json:"Code"`
|
||
|
|
Message string `json:"Message"`
|
||
|
|
} `json:"Error"`
|
||
|
|
} `json:"ResponseMetadata"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func main() {
|
||
|
|
akFile := flag.String("ak-file", "", "file containing the Volcengine AccessKey ID")
|
||
|
|
skFile := flag.String("sk-file", "", "file containing the Volcengine SecretAccessKey")
|
||
|
|
endpoint := flag.String("endpoint", "https://rtc.volcengineapi.com", "RTC OpenAPI endpoint")
|
||
|
|
rtcAppID := flag.String("rtc-app-id", "", "RTC application ID used for staged validation probes")
|
||
|
|
templateFile := flag.String("template-file", "", "voice-chat template bundle used for ProviderParams probes")
|
||
|
|
roomID := flag.String("room-id", "", "RTC room ID to inspect without starting a task")
|
||
|
|
flag.Parse()
|
||
|
|
if *akFile == "" || *skFile == "" {
|
||
|
|
panic("-ak-file and -sk-file are required")
|
||
|
|
}
|
||
|
|
ak := readSecret(*akFile)
|
||
|
|
sk := readSecret(*skFile)
|
||
|
|
credentials := volcbase.Credentials{AccessKeyID: ak, SecretAccessKey: sk, Service: "rtc", Region: "cn-north-1"}
|
||
|
|
client := &http.Client{Timeout: 15 * time.Second}
|
||
|
|
if *rtcAppID != "" && *roomID != "" {
|
||
|
|
queryRoom(client, credentials, *endpoint, *rtcAppID, *roomID)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
for _, version := range []string{"2024-06-01", "2024-12-01", "2025-06-01"} {
|
||
|
|
probe(client, credentials, *endpoint, version, "empty", map[string]any{})
|
||
|
|
}
|
||
|
|
if *rtcAppID != "" {
|
||
|
|
version := "2024-12-01"
|
||
|
|
identity := map[string]any{
|
||
|
|
"AppId": *rtcAppID, "RoomId": "probe-room", "TaskId": "probe-task",
|
||
|
|
}
|
||
|
|
agent := map[string]any{
|
||
|
|
"TargetUserId": []string{"probe-user"}, "UserId": "probe-agent",
|
||
|
|
}
|
||
|
|
probe(client, credentials, *endpoint, version, "app-only", map[string]any{"AppId": *rtcAppID})
|
||
|
|
probe(client, credentials, *endpoint, version, "identity-only", map[string]any{
|
||
|
|
"AppId": *rtcAppID, "RoomId": "probe-room", "TaskId": "probe-task",
|
||
|
|
})
|
||
|
|
probe(client, credentials, *endpoint, version, "empty-config", map[string]any{
|
||
|
|
"AppId": *rtcAppID, "RoomId": "probe-room", "TaskId": "probe-task",
|
||
|
|
"Config": map[string]any{}, "AgentConfig": map[string]any{},
|
||
|
|
})
|
||
|
|
probe(client, credentials, *endpoint, version, "agent-valid", merge(identity, map[string]any{
|
||
|
|
"Config": map[string]any{}, "AgentConfig": agent,
|
||
|
|
}))
|
||
|
|
probe(client, credentials, *endpoint, version, "s2s-shell", merge(identity, map[string]any{
|
||
|
|
"Config": map[string]any{"S2SConfig": map[string]any{}}, "AgentConfig": agent,
|
||
|
|
}))
|
||
|
|
probe(client, credentials, *endpoint, version, "s2s-provider", merge(identity, map[string]any{
|
||
|
|
"Config": map[string]any{"S2SConfig": map[string]any{
|
||
|
|
"Provider": "volcano", "OutputMode": 0,
|
||
|
|
}}, "AgentConfig": agent,
|
||
|
|
}))
|
||
|
|
probe(client, credentials, *endpoint, version, "s2s-params-empty", merge(identity, map[string]any{
|
||
|
|
"Config": map[string]any{"S2SConfig": map[string]any{
|
||
|
|
"Provider": "volcano", "OutputMode": 0, "ProviderParams": map[string]any{},
|
||
|
|
}}, "AgentConfig": agent,
|
||
|
|
}))
|
||
|
|
if *templateFile != "" {
|
||
|
|
providerParams := readProviderParams(*templateFile)
|
||
|
|
for _, item := range []struct {
|
||
|
|
label string
|
||
|
|
keys []string
|
||
|
|
}{
|
||
|
|
{label: "params-app", keys: []string{"app"}},
|
||
|
|
{label: "params-dialog", keys: []string{"dialog"}},
|
||
|
|
{label: "params-asr", keys: []string{"asr"}},
|
||
|
|
{label: "params-tts", keys: []string{"tts"}},
|
||
|
|
{label: "params-full", keys: []string{"app", "dialog", "asr", "tts"}},
|
||
|
|
} {
|
||
|
|
selected := make(map[string]any, len(item.keys))
|
||
|
|
for _, key := range item.keys {
|
||
|
|
if value, ok := providerParams[key]; ok {
|
||
|
|
selected[key] = value
|
||
|
|
}
|
||
|
|
}
|
||
|
|
probeIdentity := merge(identity, map[string]any{"TaskId": "probe-" + item.label})
|
||
|
|
payload := merge(probeIdentity, map[string]any{
|
||
|
|
"Config": map[string]any{"S2SConfig": map[string]any{
|
||
|
|
"Provider": "volcano", "OutputMode": 0, "ProviderParams": selected,
|
||
|
|
}}, "AgentConfig": agent,
|
||
|
|
})
|
||
|
|
if probeAction(client, credentials, *endpoint, version, item.label, "StartVoiceChat", payload) {
|
||
|
|
probeAction(client, credentials, *endpoint, version, item.label+"-cleanup", "StopVoiceChat", probeIdentity)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
fullTemplate := readHybridTemplate(*templateFile)
|
||
|
|
fullIdentity := merge(identity, map[string]any{"TaskId": "probe-full-template"})
|
||
|
|
fullTemplate = merge(fullTemplate, fullIdentity)
|
||
|
|
fullAgent, _ := fullTemplate["AgentConfig"].(map[string]any)
|
||
|
|
fullAgent["TargetUserId"] = []string{"probe-user"}
|
||
|
|
fullAgent["UserId"] = "probe-agent"
|
||
|
|
if probeAction(client, credentials, *endpoint, version, "full-template", "StartVoiceChat", fullTemplate) {
|
||
|
|
probeAction(client, credentials, *endpoint, version, "full-template-cleanup", "StopVoiceChat", fullIdentity)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
probeAction(client, credentials, *endpoint, version, "cleanup", "StopVoiceChat", identity)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func queryRoom(client *http.Client, credentials volcbase.Credentials, endpoint, appID, roomID string) {
|
||
|
|
target, err := url.Parse(endpoint)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
query := target.Query()
|
||
|
|
query.Set("Action", "GetRoomOnlineUsers")
|
||
|
|
query.Set("Version", "2023-11-01")
|
||
|
|
query.Set("AppId", appID)
|
||
|
|
query.Set("RoomId", roomID)
|
||
|
|
query.Set("Property", "false")
|
||
|
|
target.RawQuery = query.Encode()
|
||
|
|
request, err := http.NewRequest(http.MethodGet, target.String(), nil)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
request.Host = target.Host
|
||
|
|
request.Header.Set("Accept", "application/json")
|
||
|
|
credentials.Sign(request)
|
||
|
|
response, err := client.Do(request)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
defer response.Body.Close()
|
||
|
|
body, err := io.ReadAll(io.LimitReader(response.Body, 1<<20))
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
var decoded map[string]any
|
||
|
|
if err := json.Unmarshal(body, &decoded); err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
encoded, _ := json.Marshal(decoded)
|
||
|
|
fmt.Printf("room-status=%d response=%s\n", response.StatusCode, encoded)
|
||
|
|
}
|
||
|
|
|
||
|
|
func readProviderParams(path string) map[string]any {
|
||
|
|
template := readHybridTemplate(path)
|
||
|
|
config, _ := template["Config"].(map[string]any)
|
||
|
|
s2s, _ := config["S2SConfig"].(map[string]any)
|
||
|
|
params, _ := s2s["ProviderParams"].(map[string]any)
|
||
|
|
if params == nil {
|
||
|
|
panic("template does not contain s2s_hybrid Config.S2SConfig.ProviderParams")
|
||
|
|
}
|
||
|
|
return params
|
||
|
|
}
|
||
|
|
|
||
|
|
func readHybridTemplate(path string) map[string]any {
|
||
|
|
raw, err := os.ReadFile(path)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
var bundle map[string]any
|
||
|
|
if err := json.Unmarshal(raw, &bundle); err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
templates, _ := bundle["templates"].(map[string]any)
|
||
|
|
template, _ := templates["s2s_hybrid"].(map[string]any)
|
||
|
|
if template == nil {
|
||
|
|
panic("template does not contain s2s_hybrid")
|
||
|
|
}
|
||
|
|
return template
|
||
|
|
}
|
||
|
|
|
||
|
|
func merge(base map[string]any, extra map[string]any) map[string]any {
|
||
|
|
result := make(map[string]any, len(base)+len(extra))
|
||
|
|
for key, value := range base {
|
||
|
|
result[key] = value
|
||
|
|
}
|
||
|
|
for key, value := range extra {
|
||
|
|
result[key] = value
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
func readSecret(path string) string {
|
||
|
|
value, err := os.ReadFile(path)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
return strings.TrimSpace(string(value))
|
||
|
|
}
|
||
|
|
|
||
|
|
func probe(client *http.Client, credentials volcbase.Credentials, endpoint, version, label string, payload map[string]any) {
|
||
|
|
probeAction(client, credentials, endpoint, version, label, "StartVoiceChat", payload)
|
||
|
|
}
|
||
|
|
|
||
|
|
func probeAction(client *http.Client, credentials volcbase.Credentials, endpoint, version, label, action string, payload map[string]any) bool {
|
||
|
|
target, err := url.Parse(endpoint)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
query := target.Query()
|
||
|
|
query.Set("Action", action)
|
||
|
|
query.Set("Version", version)
|
||
|
|
target.RawQuery = query.Encode()
|
||
|
|
bodyBytes, err := json.Marshal(payload)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
request, err := http.NewRequest(http.MethodPost, target.String(), bytes.NewReader(bodyBytes))
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
request.Host = target.Host
|
||
|
|
request.Header.Set("Content-Type", "application/json")
|
||
|
|
request.Header.Set("Accept", "application/json")
|
||
|
|
credentials.Sign(request)
|
||
|
|
response, err := client.Do(request)
|
||
|
|
if err != nil {
|
||
|
|
fmt.Printf("label=%s version=%s transport_error=%v\n", label, version, err)
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
defer response.Body.Close()
|
||
|
|
body, err := io.ReadAll(io.LimitReader(response.Body, 1<<20))
|
||
|
|
if err != nil {
|
||
|
|
fmt.Printf("label=%s version=%s status=%d read_error=%v\n", label, version, response.StatusCode, err)
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
var envelope responseEnvelope
|
||
|
|
_ = json.Unmarshal(body, &envelope)
|
||
|
|
if envelope.ResponseMetadata.Error == nil {
|
||
|
|
fmt.Printf("label=%s version=%s status=%d code=none\n", label, version, response.StatusCode)
|
||
|
|
return response.StatusCode >= 200 && response.StatusCode < 300
|
||
|
|
}
|
||
|
|
fmt.Printf("label=%s version=%s status=%d code=%s message=%s\n", label, version, response.StatusCode,
|
||
|
|
envelope.ResponseMetadata.Error.Code, envelope.ResponseMetadata.Error.Message)
|
||
|
|
return false
|
||
|
|
}
|