diff --git a/README.md b/README.md
index 1d52fd6..221b768 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Atlas via long polling and an in-process cron scheduler.
|---|---|
| `util` | `/help`, `/info` (admin), `/stickerid` (owner) |
| `misc` | `/ping`, `/ping_stats` (admin), `/ff` (admin), `/xlt1`, `/giaxang` (Petrolimex retail fuel prices), `/the_answer` (owner), `/trongtruonghop` + `/tth`, `/trongtruonghopvng` + `/tthvng` disclaimers |
-| `random` | Pick one comma-separated option at random: `/random` (text), `/wheelofnames` (wheel GIF), `/gacha` (Genshin-style wish; options are 5★ by default, prefix `4*` or `3*`), `/gachabeta` (unlisted; beta version of `/gacha`). The animations use the optional wheelofnames renderer |
+| `random` | Pick one comma-separated option at random: `/random` (text), `/wheelofnames` (wheel GIF), `/gacha` (card-pack wish MP4; options are 5★ by default, prefix `4*` or `3*`). The animations use the optional wheelofnames renderer |
| `amlich` | Vietnamese lunar calendar: `/amlich` (dương lịch → âm lịch, defaults to today), `/duonglich` (âm lịch → dương lịch, `nhuan` flag for leap months); dates accept `d`, `d/m`, or `d/m/yyyy` — missing parts fill from today in the input's calendar. Years 1800–2199 only |
| `wordle` | Daily Wordle game: `/wordle [word]`, `/wordle_new`, `/wordle_giveup`, `/wordle_stats` |
| `loldle` | League-of-Legends "guess the champion": `/loldle [champion]`, `/loldle_giveup`, `/loldle_stats`, `/loldle_setmax` (owner) |
diff --git a/docs/deploy-coolify-selfhosted.md b/docs/deploy-coolify-selfhosted.md
index b810387..45af681 100644
--- a/docs/deploy-coolify-selfhosted.md
+++ b/docs/deploy-coolify-selfhosted.md
@@ -86,17 +86,13 @@ instead. With no renderer configured there is no holding message — the winner
reply is immediate.
`/gacha` uses the same service and token: the bot swaps the URL's last path
-segment, so `.../api/gif` becomes `.../api/gacha`. It renders a 7-second
-`640x360` silent MP4 wish animation, posts `Wishing...` while it renders, and
+segment, so `.../api/gif` becomes `.../api/gacha`. It renders a 6-second
+`360x640` portrait silent MP4 wish animation (a card pack torn open), posts `Wishing...` while it renders, and
falls back to a text reply such as `★★★★★ Pizza` on the same failures. Every
option is equally likely, as with `/random`; the rarity only sets what the
animation and reply show. Options are 5★ by default; prefix `4*` or `3*` to
lower one, e.g. `/gacha Pizza, 4* Pho, 3* Rice`.
-The unlisted `/gachabeta` takes the same input and renders the beta version
-of the wish from `.../api/gachabeta` on the same service as a `360x640`
-portrait MP4, with the same text fallback.
-
## 1. MongoDB Atlas (M0)
1. Create a free **M0** cluster (512 MB — ample for the tiny paper-trading KV).
diff --git a/internal/modules/random/gacha_api_client.go b/internal/modules/random/gacha_api_client.go
index 4437abc..b20ef01 100644
--- a/internal/modules/random/gacha_api_client.go
+++ b/internal/modules/random/gacha_api_client.go
@@ -10,25 +10,12 @@ import (
)
const (
- gachaRemoteFPS = 24
- gachaRemoteWidth = 640
- gachaRemoteHeight = 360
-)
-
-// gachaStyle is one wish animation the renderer serves: its path next to
-// /api/gif, 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 (
- gachaStyleWish = gachaStyle{Path: "gacha", Duration: 7, Width: gachaRemoteWidth, Height: gachaRemoteHeight}
- // The beta wish is portrait: the requested width is its long edge.
- gachaStyleBeta = gachaStyle{Path: "gachabeta", Duration: 6, Width: gachaRemoteHeight, Height: gachaRemoteWidth}
+ gachaRemoteFPS = 24
+ // gachaRemoteWidth is the requested long edge; the wish is portrait, so
+ // the video is gachaVideoWidth x gachaRemoteWidth.
+ gachaRemoteWidth = 640
+ gachaVideoWidth = 360
+ gachaDuration = 6
)
type gachaAPIRequest struct {
@@ -38,11 +25,10 @@ type gachaAPIRequest struct {
Width int `json:"width"`
}
-// gachaAPIEndpoint derives a wish renderer from the configured wheel
-// endpoint: the same service serves /api/gacha and /api/gachabeta next to
-// /api/gif, so the last path segment is swapped and no second URL needs
-// configuring.
-func gachaAPIEndpoint(rawURL, path string) (*url.URL, error) {
+// gachaAPIEndpoint derives the wish renderer from the configured wheel
+// endpoint: the same service serves /api/gacha next to /api/gif, so the last
+// path segment is swapped and no second URL needs configuring.
+func gachaAPIEndpoint(rawURL string) (*url.URL, error) {
endpoint, err := wheelAPIEndpoint(rawURL)
if err != nil {
return nil, err
@@ -50,13 +36,12 @@ func gachaAPIEndpoint(rawURL, path string) (*url.URL, error) {
base := *endpoint
base.Path = strings.TrimSuffix(base.Path, "/")
base.RawPath = ""
- return base.ResolveReference(&url.URL{Path: path}), nil
+ return base.ResolveReference(&url.URL{Path: "gacha"}), nil
}
-// RenderGacha returns the MP4 wish animation at path revealing label at
-// rarity stars.
-func (c wheelAPIClient) RenderGacha(ctx context.Context, path, label string, rarity int) ([]byte, error) {
- endpoint, err := gachaAPIEndpoint(c.URL, path)
+// RenderGacha returns the MP4 wish animation revealing label at rarity stars.
+func (c wheelAPIClient) RenderGacha(ctx context.Context, label string, rarity int) ([]byte, error) {
+ endpoint, err := gachaAPIEndpoint(c.URL)
if err != nil {
return nil, err
}
@@ -83,15 +68,15 @@ 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) (wheelAnimation, error) {
- data, err := newWheelAPIClientFromEnv().RenderGacha(ctx, style.Path, label, rarity)
+func renderGachaAnimation(ctx context.Context, label string, rarity int) (wheelAnimation, error) {
+ data, err := newWheelAPIClientFromEnv().RenderGacha(ctx, label, rarity)
if err != nil {
return wheelAnimation{}, err
}
return wheelAnimation{
Data: data,
- Duration: style.Duration,
- Width: style.Width,
- Height: style.Height,
+ Duration: gachaDuration,
+ Width: gachaVideoWidth,
+ Height: gachaRemoteWidth,
}, nil
}
diff --git a/internal/modules/random/gacha_api_client_test.go b/internal/modules/random/gacha_api_client_test.go
index 90a3f40..7114c18 100644
--- a/internal/modules/random/gacha_api_client_test.go
+++ b/internal/modules/random/gacha_api_client_test.go
@@ -13,7 +13,7 @@ func TestGachaAPIEndpoint_SwapsLastPathSegment(t *testing.T) {
"https://render.example/api/gif/": "https://render.example/api/gacha",
"http://10.0.0.5:3000/api/gif": "http://10.0.0.5:3000/api/gacha",
} {
- got, err := gachaAPIEndpoint(raw, "gacha")
+ got, err := gachaAPIEndpoint(raw)
if err != nil {
t.Fatalf("gachaAPIEndpoint(%q): %v", raw, err)
}
@@ -21,7 +21,7 @@ func TestGachaAPIEndpoint_SwapsLastPathSegment(t *testing.T) {
t.Errorf("gachaAPIEndpoint(%q) = %q, want %q", raw, got, want)
}
}
- if _, err := gachaAPIEndpoint("", "gacha"); err != errWheelAPINotConfigured {
+ if _, err := gachaAPIEndpoint(""); err != errWheelAPINotConfigured {
t.Fatalf("empty url err = %v, want errWheelAPINotConfigured", err)
}
}
@@ -38,7 +38,7 @@ func TestWheelAPIClient_RenderGachaRejectsInvalidInput(t *testing.T) {
{name: "rarity too high", label: "a", rarity: 6},
} {
t.Run(tc.name, func(t *testing.T) {
- if _, err := client.RenderGacha(context.Background(), "gacha", tc.label, tc.rarity); err == nil {
+ if _, err := client.RenderGacha(context.Background(), tc.label, tc.rarity); err == nil {
t.Fatal("RenderGacha returned nil error")
}
})
@@ -66,7 +66,7 @@ func TestWheelAPIClient_RenderGachaReturnsErrorsForBadResponses(t *testing.T) {
defer server.Close()
client := wheelAPIClient{HTTP: server.Client(), URL: server.URL + "/api/gif"}
- if _, err := client.RenderGacha(context.Background(), "gacha", "a", 3); err == nil {
+ if _, err := client.RenderGacha(context.Background(), "a", 3); err == nil {
t.Fatal("RenderGacha returned nil error")
}
})
diff --git a/internal/modules/random/gacha_command.go b/internal/modules/random/gacha_command.go
index e7b8308..7f30ff9 100644
--- a/internal/modules/random/gacha_command.go
+++ b/internal/modules/random/gacha_command.go
@@ -18,7 +18,6 @@ import (
const (
gachaUsage = "Usage: /gacha