192 lines
4.6 KiB
Go
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,
|
|
}
|
|
}
|