Add extra twitch helpers

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2020-12-24 13:18:30 +01:00
parent 6e4af652b9
commit e19fe57ec7
Signed by: luzifer
GPG Key ID: 0066F03ED215AD7D
2 changed files with 122 additions and 40 deletions

41
irc.go
View File

@ -1,11 +1,8 @@
package main package main
import ( import (
"context"
"crypto/tls" "crypto/tls"
"encoding/json"
"fmt" "fmt"
"net/http"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -34,7 +31,7 @@ type ircHandler struct {
func newIRCHandler() (*ircHandler, error) { func newIRCHandler() (*ircHandler, error) {
h := new(ircHandler) h := new(ircHandler)
username, err := h.fetchTwitchUsername() username, err := twitch.getAuthorizedUsername()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "fetching username") return nil, errors.Wrap(err, "fetching username")
} }
@ -113,42 +110,6 @@ func (i ircHandler) Handle(c *irc.Client, m *irc.Message) {
func (i ircHandler) Run() error { return errors.Wrap(i.c.Run(), "running IRC client") } func (i ircHandler) Run() error { return errors.Wrap(i.c.Run(), "running IRC client") }
func (ircHandler) fetchTwitchUsername() (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), twitchRequestTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.twitch.tv/helix/users", nil)
if err != nil {
return "", errors.Wrap(err, "assemble user request")
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Client-Id", cfg.TwitchClient)
req.Header.Set("Authorization", "Bearer "+cfg.TwitchToken)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", errors.Wrap(err, "requesting user info")
}
defer resp.Body.Close()
var payload struct {
Data []struct {
ID string `json:"id"`
Login string `json:"login"`
} `json:"data"`
}
if err = json.NewDecoder(resp.Body).Decode(&payload); err != nil {
return "", errors.Wrap(err, "parse user info")
}
if l := len(payload.Data); l != 1 {
return "", errors.Errorf("unexpected number of users returned: %d", l)
}
return payload.Data[0].Login, nil
}
func (i ircHandler) handlePermit(m *irc.Message) { func (i ircHandler) handlePermit(m *irc.Message) {
badges := i.ParseBadgeLevels(m) badges := i.ParseBadgeLevels(m)
if !badges.Has(badgeBroadcaster) && (!config.PermitAllowModerator || !badges.Has(badgeModerator)) { if !badges.Has(badgeBroadcaster) && (!config.PermitAllowModerator || !badges.Has(badgeModerator)) {

121
twitch.go Normal file
View File

@ -0,0 +1,121 @@
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"github.com/pkg/errors"
)
var twitch = twitchClient{}
type twitchClient struct{}
func (t twitchClient) getAuthorizedUsername() (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), twitchRequestTimeout)
defer cancel()
var payload struct {
Data []struct {
ID string `json:"id"`
Login string `json:"login"`
} `json:"data"`
}
if err := t.request(ctx, http.MethodGet, "https://api.twitch.tv/helix/users", nil, &payload); err != nil {
return "", errors.Wrap(err, "request channel info")
}
if l := len(payload.Data); l != 1 {
return "", errors.Errorf("unexpected number of users returned: %d", l)
}
return payload.Data[0].Login, nil
}
func (t twitchClient) getIDForUsername(username string) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), twitchRequestTimeout)
defer cancel()
var payload struct {
Data []struct {
ID string `json:"id"`
Login string `json:"login"`
} `json:"data"`
}
if err := t.request(
ctx,
http.MethodGet,
fmt.Sprintf("https://api.twitch.tv/helix/users?login=%s", username),
nil,
&payload,
); err != nil {
return "", errors.Wrap(err, "request channel info")
}
if l := len(payload.Data); l != 1 {
return "", errors.Errorf("unexpected number of users returned: %d", l)
}
return payload.Data[0].ID, nil
}
func (t twitchClient) getRecentStreamInfo(username string) (string, string, error) {
ctx, cancel := context.WithTimeout(context.Background(), twitchRequestTimeout)
defer cancel()
id, err := t.getIDForUsername(username)
if err != nil {
return "", "", errors.Wrap(err, "getting ID for username")
}
var payload struct {
Data []struct {
BroadcasterID string `json:"broadcaster_id"`
GameID string `json:"game_id"`
GameName string `json:"game_name"`
Title string `json:"title"`
} `json:"data"`
}
if err := t.request(
ctx,
http.MethodGet,
fmt.Sprintf("https://api.twitch.tv/helix/channels?broadcaster_id=%s", id),
nil,
&payload,
); err != nil {
return "", "", errors.Wrap(err, "request channel info")
}
if l := len(payload.Data); l != 1 {
return "", "", errors.Errorf("unexpected number of users returned: %d", l)
}
return payload.Data[0].GameName, payload.Data[0].Title, nil
}
func (twitchClient) request(ctx context.Context, method, url string, body io.Reader, out interface{}) error {
req, err := http.NewRequestWithContext(ctx, method, url, body)
if err != nil {
return errors.Wrap(err, "assemble request")
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Client-Id", cfg.TwitchClient)
req.Header.Set("Authorization", "Bearer "+cfg.TwitchToken)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return errors.Wrap(err, "execute request")
}
defer resp.Body.Close()
return errors.Wrap(
json.NewDecoder(resp.Body).Decode(out),
"parse user info",
)
}