Skip to content

Commit f1ffdfe

Browse files
committed
Improvents to boomer mode
1 parent b7c88ac commit f1ffdfe

7 files changed

Lines changed: 134 additions & 68 deletions

File tree

cmd/bot/bot.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"log/slog"
1818
"os"
1919
"os/signal"
20+
"path"
2021
)
2122

2223
func NewBotCommand(logger *slog.Logger) *cobra.Command {
@@ -102,12 +103,17 @@ func NewBotCommand(logger *slog.Logger) *cobra.Command {
102103
return fmt.Errorf("failed to create docs repo: %w", err)
103104
}
104105

106+
overlayCache, err := mediacache.NewOverlayCache(path.Join(mediaPath, "overlay"), logger)
107+
if err != nil {
108+
return fmt.Errorf("failed to create overlay cache")
109+
}
110+
105111
logger.Info("Starting bot...")
106112
bot, err := discord.NewBot(
107113
logger,
108114
session,
109115
searcher,
110-
render.NewExecRenderer(mediaCache, mediaPath, logger),
116+
render.NewExecRenderer(mediaCache, mediaPath, logger, overlayCache),
111117
botUsername,
112118
store.NewSRTStore(conn.Db),
113119
docsRepo,

pkg/discord/bot.go

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,8 @@ func (b *Bot) createPreview(
566566
OriginalPosition: util.ToPtr(mediaID.FormatPositionRange()),
567567
Settings: Settings{
568568
// defaults
569-
OutputFormat: OutputWebp,
570-
BoomerMode: false,
569+
OutputFormat: OutputWebp,
570+
BoomerModeNumGifs: 5,
571571
},
572572
}
573573

@@ -1045,9 +1045,9 @@ func (b *Bot) createButtons(dialog []model2.Dialog, state *PreviewState) ([]disc
10451045
Emoji: &discordgo.ComponentEmoji{
10461046
Name: "🎨",
10471047
},
1048-
Style: successBtnIfTrue(state.Settings.BoomerMode),
1048+
Style: successBtnIfTrue(state.Settings.Mode == BoomerMode),
10491049
Disabled: false,
1050-
CustomID: ToggleBoomerMode().CustomID(),
1050+
CustomID: StateSetMode(BoomerMode).CustomID(),
10511051
},
10521052
}
10531053

@@ -1067,6 +1067,48 @@ func (b *Bot) createButtons(dialog []model2.Dialog, state *PreviewState) ([]disc
10671067
})
10681068
}
10691069

1070+
boomerButtons := []discordgo.MessageComponent{}
1071+
if state.Settings.Mode == BoomerMode {
1072+
lessValue := util.IfElse(state.Settings.BoomerModeNumGifs == 1, 1, state.Settings.BoomerModeNumGifs-1)
1073+
moreValue := util.IfElse(state.Settings.BoomerModeNumGifs < 20, state.Settings.BoomerModeNumGifs+1, 20)
1074+
captionButtons = append(captionButtons, discordgo.Button{
1075+
Label: "One Gif",
1076+
Emoji: &discordgo.ComponentEmoji{
1077+
Name: "1️⃣",
1078+
},
1079+
Style: discordgo.SecondaryButton,
1080+
Disabled: false,
1081+
CustomID: SetBoomerModeNumGifs(1).CustomID(),
1082+
})
1083+
captionButtons = append(captionButtons, discordgo.Button{
1084+
Label: fmt.Sprintf("Less Gifs (%d)", lessValue),
1085+
Emoji: &discordgo.ComponentEmoji{
1086+
Name: "➖",
1087+
},
1088+
Style: discordgo.SecondaryButton,
1089+
Disabled: false,
1090+
CustomID: SetBoomerModeNumGifs(lessValue).CustomID(),
1091+
})
1092+
captionButtons = append(captionButtons, discordgo.Button{
1093+
Label: fmt.Sprintf("More Gifs (%d)", moreValue),
1094+
Emoji: &discordgo.ComponentEmoji{
1095+
Name: "➕",
1096+
},
1097+
Style: discordgo.SecondaryButton,
1098+
Disabled: false,
1099+
CustomID: SetBoomerModeNumGifs(moreValue).CustomID(),
1100+
})
1101+
captionButtons = append(captionButtons, discordgo.Button{
1102+
Label: "10 Gifs",
1103+
Emoji: &discordgo.ComponentEmoji{
1104+
Name: "🔟",
1105+
},
1106+
Style: discordgo.SecondaryButton,
1107+
Disabled: false,
1108+
CustomID: SetBoomerModeNumGifs(10).CustomID(),
1109+
})
1110+
}
1111+
10701112
postActions := []discordgo.MessageComponent{discordgo.Button{
10711113
Label: "Post",
10721114
Emoji: &discordgo.ComponentEmoji{
@@ -1136,6 +1178,9 @@ func (b *Bot) createButtons(dialog []model2.Dialog, state *PreviewState) ([]disc
11361178
if len(formatButtons) > 0 {
11371179
actions = append(actions, discordgo.ActionsRow{Components: formatButtons})
11381180
}
1181+
if len(boomerButtons) > 0 {
1182+
actions = append(actions, discordgo.ActionsRow{Components: boomerButtons})
1183+
}
11391184
actions = append(actions, discordgo.ActionsRow{Components: postActions})
11401185

11411186
return actions, nil
@@ -1519,7 +1564,7 @@ func (b *Bot) renderFile(state *PreviewState, dialog []model2.Dialog) (*discordg
15191564
render.WithCustomText(state.Settings.OverrideSubs),
15201565
render.WithStartTimestamp(startTimestamp),
15211566
render.WithEndTimestamp(endTimestamp),
1522-
render.WithGifOverlays(state.Settings.BoomerMode),
1567+
render.WithGifOverlays(util.IfElse(state.Settings.Mode == BoomerMode, state.Settings.BoomerModeNumGifs, 0)),
15231568
}
15241569
if state.Settings.Mode == CaptionMode {
15251570
options = append(options,

pkg/discord/state.go

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const StateUpdateSetShift = StateUpdateType("set_shift")
2222
const StateUpdateMode = StateUpdateType("set_mode")
2323
const StateUpdateOutputFormat = StateUpdateType("set_output_format")
2424
const StateTogglePreview = StateUpdateType("toggle_preview")
25-
const StateToggleBoomerMode = StateUpdateType("toggle_boomer_mode")
25+
const StateSetBoomerModeNumGifs = StateUpdateType("set_boomer_mode_num_gifs")
2626

2727
type Mode string
2828

@@ -31,6 +31,7 @@ const (
3131
StickerMode Mode = "sticker"
3232
CaptionMode Mode = "caption"
3333
VideoMode Mode = "video"
34+
BoomerMode Mode = "boomer"
3435
)
3536

3637
type OutputFileType string
@@ -52,7 +53,7 @@ type Settings struct {
5253
SubsEnabled bool `json:"d,omitempty"`
5354
OutputFormat OutputFileType `json:"o,omitempty"`
5455
DisablePreviewImage bool `json:"n,omitempty"`
55-
BoomerMode bool `json:"bm,omitempty"`
56+
BoomerModeNumGifs int `json:"bm,omitempty"`
5657
}
5758

5859
// rawSettings is just Settings with simple types used for encoding/decoding
@@ -66,7 +67,7 @@ type rawSettings struct {
6667
SubsEnabled bool `json:"d,omitempty"`
6768
OutputFormat OutputFileType `json:"o,omitempty"`
6869
DisablePreview bool `json:"n,omitempty"`
69-
BoomerMode bool `json:"bm,omitempty"`
70+
BoomerMode int `json:"bm,omitempty"`
7071
}
7172

7273
func (c *Settings) UnmarshalJSON(bytes []byte) error {
@@ -94,7 +95,7 @@ func (c *Settings) UnmarshalJSON(bytes []byte) error {
9495
c.SubsEnabled = raw.SubsEnabled
9596
c.OutputFormat = raw.OutputFormat
9697
c.DisablePreviewImage = raw.DisablePreview
97-
c.BoomerMode = raw.BoomerMode
98+
c.BoomerModeNumGifs = raw.BoomerMode
9899

99100
return nil
100101
}
@@ -110,7 +111,7 @@ func (c *Settings) MarshalJSON() ([]byte, error) {
110111
SubsEnabled: c.SubsEnabled,
111112
OutputFormat: c.OutputFormat,
112113
DisablePreview: c.DisablePreviewImage,
113-
BoomerMode: c.BoomerMode,
114+
BoomerMode: c.BoomerModeNumGifs,
114115
})
115116
}
116117

@@ -264,20 +265,26 @@ func (c *PreviewState) ApplyUpdate(upd StateUpdate) error {
264265
c.Settings.Shift = time.Duration(floatVal)
265266
case StateUpdateMode:
266267
if strVal, ok := upd.Value.(string); !ok {
267-
return fmt.Errorf("%s was not expected type (wanted Mode got %T)", upd.Type, upd.Value)
268+
return fmt.Errorf("%s was not expected type (wanted string got %T)", upd.Type, upd.Value)
268269
} else {
269270
c.Settings.Mode = Mode(strVal)
270271
}
271272
case StateUpdateOutputFormat:
272273
if strVal, ok := upd.Value.(string); !ok {
273-
return fmt.Errorf("%s was not expected type (wanted Mode got %T)", upd.Type, upd.Value)
274+
return fmt.Errorf("%s was not expected type (wanted string got %T)", upd.Type, upd.Value)
274275
} else {
275276
c.Settings.OutputFormat = OutputFileType(strVal)
276277
}
277278
case StateTogglePreview:
278279
c.Settings.DisablePreviewImage = !c.Settings.DisablePreviewImage
279-
case StateToggleBoomerMode:
280-
c.Settings.BoomerMode = !c.Settings.BoomerMode
280+
case StateSetBoomerModeNumGifs:
281+
if intVal, ok := upd.Value.(float64); !ok {
282+
c.Settings.BoomerModeNumGifs = 0
283+
return fmt.Errorf("%s was not expected type (wanted float64 got %T)", upd.Type, upd.Value)
284+
} else {
285+
c.Settings.BoomerModeNumGifs = int(intVal)
286+
}
287+
281288
}
282289

283290
return nil
@@ -346,8 +353,8 @@ func TogglePreview() StateUpdate {
346353
return newStateUpdate(StateTogglePreview, nil)
347354
}
348355

349-
func ToggleBoomerMode() StateUpdate {
350-
return newStateUpdate(StateToggleBoomerMode, nil)
356+
func SetBoomerModeNumGifs(num int) StateUpdate {
357+
return newStateUpdate(StateSetBoomerModeNumGifs, num)
351358
}
352359

353360
func StateSetOutputFormat(format OutputFileType) StateUpdate {

pkg/mediacache/overlays.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package mediacache
2+
3+
import (
4+
"log/slog"
5+
"math/rand/v2"
6+
"os"
7+
"path"
8+
"strings"
9+
)
10+
11+
func NewOverlayCache(overlayDir string, logger *slog.Logger) (*OverlayCache, error) {
12+
entries, err := os.ReadDir(overlayDir)
13+
if err != nil {
14+
return nil, err
15+
}
16+
cache := &OverlayCache{overlays: make([]string, 0)}
17+
for _, v := range entries {
18+
if v.IsDir() || !strings.HasSuffix(v.Name(), ".gif") {
19+
continue
20+
}
21+
cache.overlays = append(cache.overlays, path.Base(v.Name()))
22+
logger.Info("discovered overlay", slog.String("name", path.Base(v.Name())))
23+
}
24+
return cache, nil
25+
}
26+
27+
type OverlayCache struct {
28+
overlays []string
29+
}
30+
31+
func (o *OverlayCache) Random(num int) []string {
32+
random := []string{}
33+
for i := 0; i < num; i++ {
34+
random = append(random, o.overlays[rand.IntN(len(o.overlays)-1)])
35+
}
36+
return random
37+
}

pkg/render/exec.go

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/warmans/tvgif/pkg/discord/media"
99
"github.com/warmans/tvgif/pkg/mediacache"
1010
model2 "github.com/warmans/tvgif/pkg/model"
11+
"github.com/warmans/tvgif/pkg/util"
1112
"io"
1213
"log/slog"
1314
"math/rand/v2"
@@ -27,14 +28,15 @@ type Renderer interface {
2728
) (*discordgo.File, error)
2829
}
2930

30-
func NewExecRenderer(cache *mediacache.Cache, mediaPath string, logger *slog.Logger) *ExecRenderer {
31-
return &ExecRenderer{mediaCache: cache, mediaPath: mediaPath, logger: logger}
31+
func NewExecRenderer(cache *mediacache.Cache, mediaPath string, logger *slog.Logger, overlayCache *mediacache.OverlayCache) *ExecRenderer {
32+
return &ExecRenderer{mediaCache: cache, mediaPath: mediaPath, logger: logger, overlayCache: overlayCache}
3233
}
3334

3435
type ExecRenderer struct {
35-
mediaCache *mediacache.Cache
36-
mediaPath string
37-
logger *slog.Logger
36+
mediaCache *mediacache.Cache
37+
mediaPath string
38+
logger *slog.Logger
39+
overlayCache *mediacache.OverlayCache
3840
}
3941

4042
func (r *ExecRenderer) RenderFile(
@@ -65,7 +67,7 @@ func (r *ExecRenderer) RenderFile(
6567
format = "webp"
6668
}
6769

68-
_, err := r.mediaCache.Get(createFileName(customID, extension), buff, opts.disableCaching || opts.overlayGifs, func(writer io.Writer) error {
70+
_, err := r.mediaCache.Get(createFileName(customID, extension), buff, opts.disableCaching || opts.overlayGifs > 0, func(writer io.Writer) error {
6971
//video input
7072
args := [][]string{
7173
{
@@ -77,20 +79,19 @@ func (r *ExecRenderer) RenderFile(
7779

7880
filterPrefix := ""
7981
filtersStartAt := "0:v"
80-
numGifs := 5
8182

8283
// e.g. ffmpeg -i sample.mp4 -an -stream_loop -1 -i gif/hearts-1.gif -ignore_loop 0 -i sparkles.gif -ignore_loop 0 -filter_complex "[0][1]overlay=x=W/2-w/2:y=H/2-h/2:shortest=1[out];[out][2]overlay=x=W/2-w/2:y=H/2-h/2:shortest=1" sample_with_gif.gif
83-
if opts.overlayGifs {
84+
if opts.overlayGifs > 0 {
8485
filterPrefix = ""
8586

86-
for i, gif := range randomOverlays(numGifs) {
87+
for i, gif := range r.overlayCache.Random(opts.overlayGifs) {
8788

8889
randomX := rand.Float64()
8990
randomY := rand.Float64()
9091

9192
filterPrefix += fmt.Sprintf(
9293
"[%s][%d]overlay=x=(W*%0.2f):y=(H*%0.2f):shortest=1:[o%d];",
93-
ifElse(i == 0, "0", fmt.Sprintf("o%d", i-1)),
94+
util.IfElse(i == 0, "0", fmt.Sprintf("o%d", i-1)),
9495
i+1,
9596
randomX,
9697
randomY,
@@ -104,7 +105,7 @@ func (r *ExecRenderer) RenderFile(
104105
})
105106
}
106107

107-
filtersStartAt = fmt.Sprintf("o%d", numGifs-1)
108+
filtersStartAt = fmt.Sprintf("o%d", opts.overlayGifs-1)
108109

109110
}
110111

@@ -169,40 +170,3 @@ func flattenArgs(args [][]string) []string {
169170
}
170171
return out
171172
}
172-
173-
func randomOverlays(num int) []string {
174-
gifs := []string{
175-
"behappy.gif",
176-
"coffee-2.gif",
177-
"goodmorning.gif",
178-
"kot.gif",
179-
"stars-glitter.gif",
180-
"bitcoin-crypto.gif",
181-
"da-dan.gif",
182-
"minions-minion.gif",
183-
"transparent-despair.gif",
184-
"cat-cat-meme.gif",
185-
"glitter-graphics.gif",
186-
"hearts-1.gif",
187-
"sparkles.gif",
188-
"transparent-hearts.gif",
189-
"coffee-1.gif",
190-
"good-morning.gif",
191-
"heine-sparkle.gif",
192-
"spinning-skull.gif",
193-
}
194-
195-
random := []string{}
196-
for i := 0; i < num; i++ {
197-
random = append(random, gifs[rand.IntN(len(gifs)-1)])
198-
}
199-
200-
return random
201-
}
202-
203-
func ifElse[T comparable](cond bool, a T, b T) T {
204-
if cond {
205-
return a
206-
}
207-
return b
208-
}

pkg/render/ffmpeg.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ type renderOpts struct {
5959
disableSubs bool
6060
specialMode SpecialMode
6161
stickerModeOpts *StickerModeOpts
62-
overlayGifs bool
62+
overlayGifs int
6363
}
6464

6565
func WithOutputFileType(tp OutputFileType) Option {
@@ -129,9 +129,9 @@ func WithCaptionMode(enable bool) Option {
129129
}
130130
}
131131

132-
func WithGifOverlays(enable bool) Option {
132+
func WithGifOverlays(num int) Option {
133133
return func(opts *renderOpts) {
134-
opts.overlayGifs = enable
134+
opts.overlayGifs = num
135135
}
136136
}
137137

pkg/util/util.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,10 @@ func TrimStrings(s []string) []string {
126126
func CleanDialogLine(s string) string {
127127
return strings.TrimSpace(strings.Join(strings.Split(s, "\n"), " "))
128128
}
129+
130+
func IfElse[T comparable](cond bool, a T, b T) T {
131+
if cond {
132+
return a
133+
}
134+
return b
135+
}

0 commit comments

Comments
 (0)