mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-12-30 00:21:16 +00:00
[commercial] Add commercial
actor
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
9726948de8
commit
990060ce41
4 changed files with 180 additions and 0 deletions
132
internal/actors/commercial/actor.go
Normal file
132
internal/actors/commercial/actor.go
Normal file
|
@ -0,0 +1,132 @@
|
|||
package commercial
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-irc/irc"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
const (
|
||||
actorName = "commercial"
|
||||
|
||||
maxCommercialDuration = 180
|
||||
)
|
||||
|
||||
var (
|
||||
formatMessage plugins.MsgFormatter
|
||||
permCheckFn plugins.ChannelPermissionCheckFunc
|
||||
tcGetter func(string) (*twitch.Client, error)
|
||||
|
||||
commercialChatcommandRegex = regexp.MustCompile(`^/commercial ([0-9]+)$`)
|
||||
)
|
||||
|
||||
func Register(args plugins.RegistrationArguments) error {
|
||||
formatMessage = args.FormatMessage
|
||||
permCheckFn = args.HasPermissionForChannel
|
||||
tcGetter = args.GetTwitchClientForChannel
|
||||
|
||||
args.RegisterActor(actorName, func() plugins.Actor { return &actor{} })
|
||||
|
||||
args.RegisterActorDocumentation(plugins.ActionDocumentation{
|
||||
Description: "Start Commercial",
|
||||
Name: "Commercial",
|
||||
Type: actorName,
|
||||
|
||||
Fields: []plugins.ActionDocumentationField{
|
||||
{
|
||||
Default: "",
|
||||
Description: "Duration of the commercial (must not be longer than 180s and must yield an integer)",
|
||||
Key: "duration",
|
||||
Name: "Duration",
|
||||
Optional: false,
|
||||
SupportTemplate: true,
|
||||
Type: plugins.ActionDocumentationFieldTypeString,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
args.RegisterMessageModFunc("/commercial", handleChatCommand)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type actor struct{}
|
||||
|
||||
func (a actor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
ptrStringEmpty := func(v string) *string { return &v }("")
|
||||
|
||||
durationStr, err := formatMessage(attrs.MustString("duration", ptrStringEmpty), m, r, eventData)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "executing duration template")
|
||||
}
|
||||
|
||||
return false, startCommercial(strings.TrimLeft(plugins.DeriveChannel(m, eventData), "#"), durationStr)
|
||||
}
|
||||
|
||||
func (a actor) IsAsync() bool { return false }
|
||||
func (a actor) Name() string { return actorName }
|
||||
|
||||
func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
durationTemplate, err := attrs.String("duration")
|
||||
if err != nil || durationTemplate == "" {
|
||||
return errors.New("duration must be non-empty string")
|
||||
}
|
||||
|
||||
if err = tplValidator(durationTemplate); err != nil {
|
||||
return errors.Wrap(err, "validating duration template")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleChatCommand(m *irc.Message) error {
|
||||
channel := strings.TrimLeft(plugins.DeriveChannel(m, nil), "#")
|
||||
|
||||
matches := commercialChatcommandRegex.FindStringSubmatch(m.Trailing())
|
||||
if matches == nil {
|
||||
return errors.New("ban message does not match required format")
|
||||
}
|
||||
|
||||
if err := startCommercial(channel, matches[1]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return plugins.ErrSkipSendingMessage
|
||||
}
|
||||
|
||||
func startCommercial(channel, durationStr string) error {
|
||||
duration, err := strconv.ParseInt(durationStr, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parsing duration to integer")
|
||||
}
|
||||
|
||||
if duration > maxCommercialDuration {
|
||||
return errors.New("duration too long")
|
||||
}
|
||||
|
||||
ok, err := permCheckFn(channel, twitch.ScopeChannelEditCommercial)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "checking for channel permissions")
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return errors.Errorf("channel %q is missing permission %s", channel, twitch.ScopeChannelEditCommercial)
|
||||
}
|
||||
|
||||
tc, err := tcGetter(channel)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting channel twitch-client")
|
||||
}
|
||||
|
||||
return errors.Wrap(
|
||||
tc.RunCommercial(context.Background(), channel, duration),
|
||||
"running commercial",
|
||||
)
|
||||
}
|
|
@ -129,3 +129,36 @@ func (c *Client) RemoveChannelVIP(ctx context.Context, broadcasterName, userName
|
|||
"executing request",
|
||||
)
|
||||
}
|
||||
|
||||
// RunCommercial starts a commercial on the specified channel
|
||||
func (c *Client) RunCommercial(ctx context.Context, channel string, duration int64) error {
|
||||
channelID, err := c.GetIDForUsername(channel)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting ID for channel name")
|
||||
}
|
||||
|
||||
payload := struct {
|
||||
BroadcasterID string `json:"broadcaster_id"`
|
||||
Length int64 `json:"length"`
|
||||
}{
|
||||
BroadcasterID: channelID,
|
||||
Length: duration,
|
||||
}
|
||||
|
||||
body := new(bytes.Buffer)
|
||||
if err := json.NewEncoder(body).Encode(payload); err != nil {
|
||||
return errors.Wrap(err, "encoding payload")
|
||||
}
|
||||
|
||||
return errors.Wrap(
|
||||
c.request(clientRequestOpts{
|
||||
AuthType: authTypeBearerToken,
|
||||
Body: body,
|
||||
Context: ctx,
|
||||
Method: http.MethodPost,
|
||||
OKStatus: http.StatusOK,
|
||||
URL: "https://api.twitch.tv/helix/channels/commercial",
|
||||
}),
|
||||
"executing request",
|
||||
)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/Luzifer/go_helpers/v2/str"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/announce"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/ban"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/commercial"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/counter"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/delay"
|
||||
deleteactor "github.com/Luzifer/twitch-bot/v3/internal/actors/delete"
|
||||
|
@ -51,6 +52,7 @@ var (
|
|||
// Actors
|
||||
announce.Register,
|
||||
ban.Register,
|
||||
commercial.Register,
|
||||
counter.Register,
|
||||
delay.Register,
|
||||
deleteactor.Register,
|
||||
|
|
|
@ -44,6 +44,19 @@ Ban user from chat
|
|||
reason: ""
|
||||
```
|
||||
|
||||
## Commercial
|
||||
|
||||
Start Commercial
|
||||
|
||||
```yaml
|
||||
- type: commercial
|
||||
attributes:
|
||||
# Duration of the commercial (must not be longer than 180s and must yield an integer)
|
||||
# Optional: false
|
||||
# Type: string (Supports Templating)
|
||||
duration: ""
|
||||
```
|
||||
|
||||
## Custom Event
|
||||
|
||||
Create a custom event
|
||||
|
|
Loading…
Reference in a new issue