mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-11-09 16:50:01 +00:00
[vip/unvip] Implement actors and chat commands
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
f0dfea1728
commit
f9716d6591
3 changed files with 232 additions and 0 deletions
196
internal/actors/vip/vip.go
Normal file
196
internal/actors/vip/vip.go
Normal file
|
@ -0,0 +1,196 @@
|
|||
package vip
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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"
|
||||
)
|
||||
|
||||
var (
|
||||
formatMessage plugins.MsgFormatter
|
||||
permCheckFn plugins.ChannelPermissionCheckFunc
|
||||
tcGetter func(string) (*twitch.Client, error)
|
||||
|
||||
ptrStringEmpty = func(s string) *string { return &s }("")
|
||||
)
|
||||
|
||||
func Register(args plugins.RegistrationArguments) error {
|
||||
formatMessage = args.FormatMessage
|
||||
permCheckFn = args.HasPermissionForChannel
|
||||
tcGetter = args.GetTwitchClientForChannel
|
||||
|
||||
args.RegisterActor("vip", func() plugins.Actor { return &vipActor{} })
|
||||
args.RegisterActor("unvip", func() plugins.Actor { return &unvipActor{} })
|
||||
|
||||
args.RegisterActorDocumentation(plugins.ActionDocumentation{
|
||||
Description: "Add VIP for the given channel",
|
||||
Name: "Add VIP",
|
||||
Type: "vip",
|
||||
|
||||
Fields: []plugins.ActionDocumentationField{
|
||||
{
|
||||
Default: "",
|
||||
Description: "Channel to add the VIP to",
|
||||
Key: "channel",
|
||||
Name: "Channel",
|
||||
Optional: false,
|
||||
SupportTemplate: true,
|
||||
Type: plugins.ActionDocumentationFieldTypeString,
|
||||
},
|
||||
{
|
||||
Default: "",
|
||||
Description: "User to add as VIP",
|
||||
Key: "user",
|
||||
Name: "User",
|
||||
Optional: false,
|
||||
SupportTemplate: true,
|
||||
Type: plugins.ActionDocumentationFieldTypeString,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
args.RegisterActorDocumentation(plugins.ActionDocumentation{
|
||||
Description: "Remove VIP for the given channel",
|
||||
Name: "Remove VIP",
|
||||
Type: "unvip",
|
||||
|
||||
Fields: []plugins.ActionDocumentationField{
|
||||
{
|
||||
Default: "",
|
||||
Description: "Channel to remove the VIP from",
|
||||
Key: "channel",
|
||||
Name: "Channel",
|
||||
Optional: false,
|
||||
SupportTemplate: true,
|
||||
Type: plugins.ActionDocumentationFieldTypeString,
|
||||
},
|
||||
{
|
||||
Default: "",
|
||||
Description: "User to remove as VIP",
|
||||
Key: "user",
|
||||
Name: "User",
|
||||
Optional: false,
|
||||
SupportTemplate: true,
|
||||
Type: plugins.ActionDocumentationFieldTypeString,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
args.RegisterMessageModFunc("/vip", handleAddVIP)
|
||||
args.RegisterMessageModFunc("/unvip", handleRemoveVIP)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Actor
|
||||
|
||||
type (
|
||||
actor struct{}
|
||||
unvipActor struct{ actor }
|
||||
vipActor struct{ actor }
|
||||
)
|
||||
|
||||
func (actor) IsAsync() bool { return false }
|
||||
func (a actor) Validate(tplValidator plugins.TemplateValidatorFunc, attrs *plugins.FieldCollection) (err error) {
|
||||
for _, field := range []string{"channel", "user"} {
|
||||
if v, err := attrs.String(field); err != nil || v == "" {
|
||||
return errors.Errorf("%s must be non-empty string", field)
|
||||
}
|
||||
|
||||
if err = tplValidator(attrs.MustString(field, ptrStringEmpty)); err != nil {
|
||||
return errors.Wrapf(err, "validating %s template", field)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a actor) getParams(m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (channel, user string, err error) {
|
||||
if channel, err = formatMessage(attrs.MustString("channel", nil), m, r, eventData); err != nil {
|
||||
return "", "", errors.Wrap(err, "parsing channel")
|
||||
}
|
||||
|
||||
if user, err = formatMessage(attrs.MustString("user", nil), m, r, eventData); err != nil {
|
||||
return "", "", errors.Wrap(err, "parsing user")
|
||||
}
|
||||
|
||||
return strings.TrimLeft(channel, "#"), user, nil
|
||||
}
|
||||
|
||||
func (u unvipActor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
channel, user, err := u.getParams(m, r, eventData, attrs)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "getting parameters")
|
||||
}
|
||||
|
||||
return false, errors.Wrap(
|
||||
executeModVIP(channel, func(tc *twitch.Client) error { return tc.RemoveChannelVIP(context.Background(), channel, user) }),
|
||||
"removing VIP",
|
||||
)
|
||||
}
|
||||
|
||||
func (unvipActor) Name() string { return "unvip" }
|
||||
|
||||
func (v vipActor) Execute(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *plugins.FieldCollection, attrs *plugins.FieldCollection) (preventCooldown bool, err error) {
|
||||
channel, user, err := v.getParams(m, r, eventData, attrs)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "getting parameters")
|
||||
}
|
||||
|
||||
return false, errors.Wrap(
|
||||
executeModVIP(channel, func(tc *twitch.Client) error { return tc.AddChannelVIP(context.Background(), channel, user) }),
|
||||
"adding VIP",
|
||||
)
|
||||
}
|
||||
|
||||
func (vipActor) Name() string { return "vip" }
|
||||
|
||||
// Generic helper
|
||||
|
||||
func executeModVIP(channel string, modFn func(tc *twitch.Client) error) error {
|
||||
ok, err := permCheckFn(channel, twitch.ScopeChannelManageVIPS)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "checking for channel permissions")
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return errors.Errorf("channel %q is missing permission %s", channel, twitch.ScopeChannelManageVIPS)
|
||||
}
|
||||
|
||||
tc, err := tcGetter(channel)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting channel twitch-client")
|
||||
}
|
||||
|
||||
return modFn(tc)
|
||||
}
|
||||
|
||||
// Chat-Commands
|
||||
|
||||
func handleAddVIP(m *irc.Message) error {
|
||||
return handleModVIP(m, func(tc *twitch.Client, channel, user string) error {
|
||||
return errors.Wrap(tc.AddChannelVIP(context.Background(), channel, user), "adding VIP")
|
||||
})
|
||||
}
|
||||
|
||||
func handleModVIP(m *irc.Message, modFn func(tc *twitch.Client, channel, user string) error) error {
|
||||
channel := strings.TrimLeft(plugins.DeriveChannel(m, nil), "#")
|
||||
|
||||
parts := strings.Split(m.Trailing(), " ")
|
||||
if len(parts) != 2 { //nolint:gomnd // Just a count, makes no sense as a constant
|
||||
return errors.Errorf("wrong command usage, must consist of 2 words")
|
||||
}
|
||||
|
||||
return executeModVIP(channel, func(tc *twitch.Client) error { return modFn(tc, channel, parts[1]) })
|
||||
}
|
||||
|
||||
func handleRemoveVIP(m *irc.Message) error {
|
||||
return handleModVIP(m, func(tc *twitch.Client, channel, user string) error {
|
||||
return errors.Wrap(tc.RemoveChannelVIP(context.Background(), channel, user), "removing VIP")
|
||||
})
|
||||
}
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/Luzifer/twitch-bot/v3/internal/actors/respond"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/timeout"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/variables"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/vip"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/actors/whisper"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/apimodules/customevent"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/apimodules/msgformat"
|
||||
|
@ -57,6 +58,7 @@ var (
|
|||
respond.Register,
|
||||
timeout.Register,
|
||||
variables.Register,
|
||||
vip.Register,
|
||||
whisper.Register,
|
||||
|
||||
// Template functions
|
||||
|
|
|
@ -1,6 +1,23 @@
|
|||
# Available Actions
|
||||
|
||||
|
||||
## Add VIP
|
||||
|
||||
Add VIP for the given channel
|
||||
|
||||
```yaml
|
||||
- type: vip
|
||||
attributes:
|
||||
# Channel to add the VIP to
|
||||
# Optional: false
|
||||
# Type: string (Supports Templating)
|
||||
channel: ""
|
||||
# User to add as VIP
|
||||
# Optional: false
|
||||
# Type: string (Supports Templating)
|
||||
user: ""
|
||||
```
|
||||
|
||||
## Ban User
|
||||
|
||||
Ban user from chat
|
||||
|
@ -225,6 +242,23 @@ Manage a database of quotes in your channel
|
|||
format: "Quote #{{ .index }}: {{ .quote }}"
|
||||
```
|
||||
|
||||
## Remove VIP
|
||||
|
||||
Remove VIP for the given channel
|
||||
|
||||
```yaml
|
||||
- type: unvip
|
||||
attributes:
|
||||
# Channel to remove the VIP from
|
||||
# Optional: false
|
||||
# Type: string (Supports Templating)
|
||||
channel: ""
|
||||
# User to remove as VIP
|
||||
# Optional: false
|
||||
# Type: string (Supports Templating)
|
||||
user: ""
|
||||
```
|
||||
|
||||
## Reset User Punishment
|
||||
|
||||
Reset punishment level for user
|
||||
|
|
Loading…
Reference in a new issue