Files
kra-new/tmp/live_acceptance/main.go
T
2026-09-23 17:42:55 +08:00

192 lines
4.6 KiB
Go

package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"net/http/cookiejar"
"os"
"path/filepath"
"time"
"kra/internal/service/dto"
)
const (
baseURL = "http://127.0.0.1:18080"
wsURL = "ws://127.0.0.1:18080/ws"
outputDir = ".tmp-live-acceptance"
adminPassword = "LocalAdmin_2026!"
userPassword = "LocalAccept_2026!"
)
type apiClient struct {
http *http.Client
token string
}
type envelope struct {
Code int `json:"code"`
Data json.RawMessage `json:"data"`
Msg string `json:"msg"`
}
type account struct {
Username string `json:"username"`
Password string `json:"password"`
ID uint `json:"id"`
}
type fixtures struct {
BaseURL string `json:"baseUrl"`
Database string `json:"database"`
CreatedAt string `json:"createdAt"`
Admin account `json:"admin"`
Anchor account `json:"anchor"`
Viewer account `json:"viewer"`
Other account `json:"other"`
CategoryID uint `json:"categoryId"`
RoomID uint `json:"roomId"`
ReplayID uint `json:"replayRoomId"`
DisabledID uint `json:"disabledRoomId"`
BrowserID uint `json:"browserRoomId,omitempty"`
GiftID uint `json:"giftId"`
Checks []string `json:"setupChecks"`
}
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
if len(os.Args) != 2 {
log.Fatal("usage: go run ./tmp/live_acceptance <setup|verify|publisher|mock-payment|browser-room>")
}
var err error
switch os.Args[1] {
case "setup":
err = setup()
case "verify":
err = verify()
case "publisher":
err = holdPublisher()
case "mock-payment":
err = serveMockPayments()
case "browser-room":
err = setupBrowserRoom()
default:
err = errors.New("unknown command")
}
if err != nil {
log.Fatal(err)
}
}
func newClient() *apiClient {
jar, _ := cookiejar.New(nil)
return &apiClient{http: &http.Client{Jar: jar, Timeout: 30 * time.Second}}
}
func (c *apiClient) call(method, path string, body, out any) error {
var reader io.Reader
if body != nil {
data, err := json.Marshal(body)
if err != nil {
return err
}
reader = bytes.NewReader(data)
}
req, err := http.NewRequest(method, baseURL+path, reader)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
if c.token != "" {
req.Header.Set("x-token", c.token)
}
response, err := c.http.Do(req)
if err != nil {
return err
}
defer response.Body.Close()
var result envelope
if err = json.NewDecoder(response.Body).Decode(&result); err != nil {
return fmt.Errorf("%s %s status=%d: %w", method, path, response.StatusCode, err)
}
if result.Code != 0 || response.StatusCode >= 400 {
return fmt.Errorf("%s %s status=%d code=%d: %s", method, path, response.StatusCode, result.Code, result.Msg)
}
if out != nil {
return json.Unmarshal(result.Data, out)
}
return nil
}
func login(user account, admin bool) (*apiClient, error) {
c := newClient()
path := "/live/client/auth/login"
if admin {
path = "/base/login"
}
var result struct {
Token string `json:"token"`
}
if err := c.call("POST", path, map[string]any{"username": user.Username, "password": user.Password}, &result); err != nil {
return nil, err
}
if result.Token == "" {
return nil, errors.New("login returned no token")
}
c.token = result.Token
return c, nil
}
func readFixtures() (*fixtures, error) {
raw, err := os.ReadFile(filepath.Join(outputDir, "fixtures.json"))
if err != nil {
return nil, err
}
var f fixtures
if err = json.Unmarshal(raw, &f); err != nil {
return nil, err
}
absolute, err := filepath.Abs(filepath.Join(outputDir, "acceptance.db"))
if err != nil || f.Database != absolute || f.BaseURL != baseURL {
return nil, errors.New("fixture points outside the isolated acceptance environment")
}
return &f, nil
}
func saveJSON(name string, value any) error {
data, err := json.MarshalIndent(value, "", " ")
if err != nil {
return err
}
return os.WriteFile(filepath.Join(outputDir, name), append(data, '\n'), 0600)
}
func must(err error) {
if err != nil {
panic(err)
}
}
func check(condition bool, format string, args ...any) {
if !condition {
panic(fmt.Sprintf(format, args...))
}
}
func roomPath(id uint) string { return fmt.Sprintf("/live/rooms/%d", id) }
func adminRoomPath(id uint) string { return fmt.Sprintf("/live/admin/rooms/%d", id) }
func makeRoom(name string, categoryID, anchorID uint, replay string, enabled bool) dto.LiveRoomRequest {
return dto.LiveRoomRequest{
Name: name, CategoryID: categoryID, AnchorUserID: anchorID,
CoverURL: "/uploads/acceptance-cover.jpg", Intro: "Local isolated acceptance room",
ReplayURL: replay, Enabled: enabled,
}
}