mirror of
https://github.com/tiennm99/miti99bot.git
synced 2026-10-04 16:13:51 +00:00
The bot now takes the renderer's base URL and appends each /api/<name> route itself, instead of taking the full /api/gif endpoint and swapping its last path segment for /gacha and /genshin. The client, its files, and its errors are named after the renderer rather than wheelofnames; the /wheelofnames command keeps its name. BREAKING CHANGE: WHEELOFNAMES_API_URL is replaced by RENDERER_URL, which holds the base URL (e.g. http://renderer:3000) rather than the /api/gif endpoint. compose.yml sets it, so Coolify needs no value.
82 lines
2.2 KiB
Go
82 lines
2.2 KiB
Go
package random
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
gachaRemoteFPS = 24
|
|
gachaRemoteWidth = 640
|
|
gachaRemoteHeight = 360
|
|
)
|
|
|
|
// gachaStyle is one wish animation the renderer serves: its route name under
|
|
// /api, the clip length in seconds, and the frame size it renders for a
|
|
// gachaRemoteWidth request.
|
|
type gachaStyle struct {
|
|
Path string
|
|
Duration int
|
|
Width int
|
|
Height int
|
|
}
|
|
|
|
var (
|
|
// The card-pack wish is portrait: the requested width is its long edge.
|
|
gachaStyleCardPack = gachaStyle{Path: "gacha", Duration: 6, Width: gachaRemoteHeight, Height: gachaRemoteWidth}
|
|
gachaStyleGenshin = gachaStyle{Path: "genshin", Duration: 7, Width: gachaRemoteWidth, Height: gachaRemoteHeight}
|
|
)
|
|
|
|
type gachaRenderRequest struct {
|
|
Label string `json:"label"`
|
|
Rarity int `json:"rarity"`
|
|
FPS int `json:"fps"`
|
|
Width int `json:"width"`
|
|
}
|
|
|
|
// RenderGacha returns the MP4 wish animation named path revealing label at
|
|
// rarity stars.
|
|
func (c rendererClient) RenderGacha(ctx context.Context, path, label string, rarity int) ([]byte, error) {
|
|
endpoint, err := c.endpoint(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if strings.TrimSpace(label) == "" {
|
|
return nil, fmt.Errorf("renderer gacha label empty")
|
|
}
|
|
if rarity < gachaMinRarity || rarity > gachaMaxRarity {
|
|
return nil, fmt.Errorf("renderer gacha rarity %d out of range", rarity)
|
|
}
|
|
body, err := json.Marshal(gachaRenderRequest{
|
|
Label: label,
|
|
Rarity: rarity,
|
|
FPS: gachaRemoteFPS,
|
|
Width: gachaRemoteWidth,
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("renderer gacha request encode failed: %w", err)
|
|
}
|
|
return c.post(ctx, endpoint, body, "video/mp4", isMP4)
|
|
}
|
|
|
|
// isMP4 checks for the ISO base media "ftyp" box that opens every MP4.
|
|
func isMP4(data []byte) bool {
|
|
return len(data) >= 8 && bytes.Equal(data[4:8], []byte("ftyp"))
|
|
}
|
|
|
|
func renderGachaAnimation(ctx context.Context, style gachaStyle, label string, rarity int) (renderedAnimation, error) {
|
|
data, err := newRendererClientFromEnv().RenderGacha(ctx, style.Path, label, rarity)
|
|
if err != nil {
|
|
return renderedAnimation{}, err
|
|
}
|
|
return renderedAnimation{
|
|
Data: data,
|
|
Duration: style.Duration,
|
|
Width: style.Width,
|
|
Height: style.Height,
|
|
}, nil
|
|
}
|