Add Discord Invite Connector
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
b3cc7e8d9a
commit
8d438c6c01
3 changed files with 203 additions and 0 deletions
29
README.md
29
README.md
|
@ -16,6 +16,35 @@ Pretty-print issues Twitch AutoMod had with the message
|
|||
match_message: '!autodebug (.+)'
|
||||
```
|
||||
|
||||
## dc-invite
|
||||
|
||||
Create a Discord invite and send the invite link through a whisper
|
||||
|
||||
```yaml
|
||||
- description: Discord-Invite
|
||||
actions:
|
||||
- type: script
|
||||
attributes:
|
||||
command:
|
||||
- /data/bin/dc-invite
|
||||
- --channel-id=1234... # Right-click on channel, copy ID
|
||||
#- --discord-bot-token=... # Can provide through env: DISCORD_BOT_TOKEN
|
||||
- --message-template
|
||||
- 'Hey, hier ist der Invite für meinen Discord: https://discord.gg/%s'
|
||||
- --send-to={{ fixUsername .user }}
|
||||
- type: discordhook
|
||||
attributes:
|
||||
content: |
|
||||
Ein Discord-Invite (`{{ .invite_code }}`) wurde erstellt:
|
||||
`{{ fixUsername .user }}` ({{ .user_id }})
|
||||
hook_url: https://discord.com/api/webhooks/...
|
||||
username: Invite-Bot
|
||||
match_channels:
|
||||
- '#luziferus'
|
||||
match_event: channelpoint_redeem
|
||||
disable_on_template: '{{ ne .reward_id "45d441e9-6a00-4c3e-8bd8-b2cd8b913753" }}'
|
||||
```
|
||||
|
||||
## dice
|
||||
|
||||
Throw `N` `M`-sided dices and print the result into the chat
|
||||
|
|
81
dc-invite/invite.go
Normal file
81
dc-invite/invite.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const discordRequestTimeout = 2 * time.Second
|
||||
|
||||
type (
|
||||
createChannelInviteReq struct {
|
||||
MaxAge int64 `json:"max_age"`
|
||||
MaxUses int64 `json:"max_uses"`
|
||||
Temporary bool `json:"temporary"`
|
||||
Unique bool `json:"unique"`
|
||||
// more unsupported params
|
||||
}
|
||||
|
||||
createChannelInviteResp struct {
|
||||
Code string `json:"code"`
|
||||
// more unsupported params
|
||||
}
|
||||
)
|
||||
|
||||
func createInvite() (string, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), discordRequestTimeout)
|
||||
defer cancel()
|
||||
|
||||
var (
|
||||
body = new(bytes.Buffer)
|
||||
err error
|
||||
reqURL = fmt.Sprintf("https://discord.com/api/channels/%s/invites", cfg.ChannelID)
|
||||
)
|
||||
|
||||
if err = json.NewEncoder(body).Encode(createChannelInviteReq{
|
||||
MaxAge: int64(cfg.ExpireIn / time.Second),
|
||||
MaxUses: cfg.Uses,
|
||||
Temporary: false,
|
||||
Unique: true,
|
||||
}); err != nil {
|
||||
return "", errors.Wrap(err, "encoding request body")
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, reqURL, body)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "creating request")
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", strings.Join([]string{"Bot", cfg.DiscordBotToken}, " "))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-Audit-Log-Reason", fmt.Sprintf("twitch-bot-tools/dc-invite requested for %s", cfg.SendTo))
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "executing request")
|
||||
}
|
||||
defer func() {
|
||||
if err := resp.Body.Close(); err != nil {
|
||||
logrus.WithError(err).Error("closing response body (leaked fd)")
|
||||
}
|
||||
}()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", errors.Errorf("unexpected status %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var invite createChannelInviteResp
|
||||
if err = json.NewDecoder(resp.Body).Decode(&invite); err != nil {
|
||||
return "", errors.Wrap(err, "decoding invite response")
|
||||
}
|
||||
|
||||
return invite.Code, nil
|
||||
}
|
93
dc-invite/main.go
Normal file
93
dc-invite/main.go
Normal file
|
@ -0,0 +1,93 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/Luzifer/rconfig/v2"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
var (
|
||||
cfg = struct {
|
||||
ChannelID string `flag:"channel-id,c" default:"" description:"Snowflake ID of the channel to invite to" validate:"nonzero"`
|
||||
DiscordBotToken string `flag:"discord-bot-token,t" default:"" description:"Token for a Bot with CREATE_INSTANT_INVITE permission" validate:"nonzero"`
|
||||
ExpireIn time.Duration `flag:"expire-in,e" default:"24h" description:"How long should the invite be valid"`
|
||||
LogLevel string `flag:"log-level" default:"info" description:"Log level (debug, info, warn, error, fatal)"`
|
||||
MessageTemplate string `flag:"message-template,m" default:"Your discord invite: https://discord.gg/%s" description:"Message to send in the whisper (use %s at the position of the invite code)"`
|
||||
SendTo string `flag:"send-to,s" default:"" description:"Twitch user to whisper the code to"`
|
||||
VersionAndExit bool `flag:"version" default:"false" description:"Prints current version and exits"`
|
||||
Uses int64 `flag:"uses,u" default:"1" description:"Expire after N uses"`
|
||||
}{}
|
||||
|
||||
version = "dev"
|
||||
)
|
||||
|
||||
func initApp() error {
|
||||
rconfig.AutoEnv(true)
|
||||
if err := rconfig.ParseAndValidate(&cfg); err != nil {
|
||||
return errors.Wrap(err, "parsing cli options")
|
||||
}
|
||||
|
||||
l, err := logrus.ParseLevel(cfg.LogLevel)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parsing log-level")
|
||||
}
|
||||
logrus.SetLevel(l)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
if err = initApp(); err != nil {
|
||||
logrus.WithError(err).Fatal("initializing app")
|
||||
}
|
||||
|
||||
if cfg.VersionAndExit {
|
||||
logrus.WithField("version", version).Info("twitch-bot-tools/dc-invite")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
invite, err := createInvite()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("creating invite")
|
||||
}
|
||||
|
||||
fieldsPayload := new(bytes.Buffer)
|
||||
if err = json.NewEncoder(fieldsPayload).Encode(map[string]any{
|
||||
"invite_code": invite,
|
||||
}); err != nil {
|
||||
logrus.WithError(err).Fatal("encoding fields payload")
|
||||
}
|
||||
|
||||
if err = json.NewEncoder(os.Stdout).Encode([]plugins.RuleAction{
|
||||
{
|
||||
Type: "eventmod",
|
||||
Attributes: plugins.FieldCollectionFromData(map[string]any{
|
||||
"fields": fieldsPayload.String(),
|
||||
}),
|
||||
},
|
||||
{
|
||||
Type: "log",
|
||||
Attributes: plugins.FieldCollectionFromData(map[string]any{
|
||||
"message": fmt.Sprintf("twitch-bot-tools/dc-invite: created invite %s for user %s", invite, cfg.SendTo),
|
||||
}),
|
||||
},
|
||||
{
|
||||
Type: "whisper",
|
||||
Attributes: plugins.FieldCollectionFromData(map[string]any{
|
||||
"message": fmt.Sprintf(cfg.MessageTemplate, invite),
|
||||
"to": cfg.SendTo,
|
||||
}),
|
||||
},
|
||||
}); err != nil {
|
||||
logrus.WithError(err).Fatal("encoding bot actions")
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue