[template] Add lastPoll function

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2023-05-21 15:24:43 +02:00
parent 04648a22e0
commit 79fb09469c
Signed by: luzifer
GPG key ID: D91C3E91E4CAD6F5
3 changed files with 109 additions and 0 deletions

View file

@ -1,11 +1,13 @@
package main
import (
"context"
"strings"
"time"
"github.com/pkg/errors"
"github.com/Luzifer/twitch-bot/v3/internal/service/access"
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
"github.com/Luzifer/twitch-bot/v3/plugins"
)
@ -16,6 +18,7 @@ func init() {
tplFuncs.Register("followAge", plugins.GenericTemplateFunctionGetter(tplTwitchFollowAge))
tplFuncs.Register("followDate", plugins.GenericTemplateFunctionGetter(tplTwitchFollowDate))
tplFuncs.Register("doesFollowLongerThan", plugins.GenericTemplateFunctionGetter(tplTwitchDoesFollowLongerThan))
tplFuncs.Register("lastPoll", plugins.GenericTemplateFunctionGetter(tplTwitchLastPoll))
tplFuncs.Register("recentGame", plugins.GenericTemplateFunctionGetter(tplTwitchRecentGame))
tplFuncs.Register("recentTitle", plugins.GenericTemplateFunctionGetter(tplTwitchRecentTitle))
tplFuncs.Register("streamUptime", plugins.GenericTemplateFunctionGetter(tplTwitchStreamUptime))
@ -85,6 +88,28 @@ func tplTwitchDoesFollowLongerThan(from, to string, t any) (bool, error) {
}
}
func tplTwitchLastPoll(username string) (*twitch.PollInfo, error) {
hasPollAccess, err := accessService.HasAnyPermissionForChannel(username, twitch.ScopeChannelReadPolls, twitch.ScopeChannelManagePolls)
if err != nil {
return nil, errors.Wrap(err, "checking read-poll-permission")
}
if !hasPollAccess {
return nil, errors.Errorf("not authorized to read polls for channel %s", username)
}
tc, err := accessService.GetTwitchClientForChannel(strings.TrimLeft(username, "#"), access.ClientConfig{
TwitchClient: cfg.TwitchClient,
TwitchClientSecret: cfg.TwitchClientSecret,
})
if err != nil {
return nil, errors.Wrap(err, "getting twitch client for user")
}
poll, err := tc.GetLatestPoll(context.Background(), strings.TrimLeft(username, "#"))
return poll, errors.Wrap(err, "getting last poll")
}
func tplTwitchRecentGame(username string, v ...string) (string, error) {
game, _, err := twitchClient.GetRecentStreamInfo(strings.TrimLeft(username, "#"))
if len(v) > 0 && (err != nil || game == "") {

69
pkg/twitch/polls.go Normal file
View file

@ -0,0 +1,69 @@
package twitch
import (
"context"
"fmt"
"net/http"
"time"
"github.com/pkg/errors"
)
const pollCacheTimeout = 10 * time.Second // Cache polls for a short moment to prevent multiple requests in one template
type (
PollInfo struct {
ID string `json:"id"`
BroadcasterID string `json:"broadcaster_id"`
BroadcasterName string `json:"broadcaster_name"`
BroadcasterLogin string `json:"broadcaster_login"`
Title string `json:"title"`
Choices []struct {
ID string `json:"id"`
Title string `json:"title"`
Votes int `json:"votes"`
ChannelPointsVotes int `json:"channel_points_votes"`
} `json:"choices"`
ChannelPointsVotingEnabled bool `json:"channel_points_voting_enabled"`
ChannelPointsPerVote int `json:"channel_points_per_vote"`
Status string `json:"status"`
Duration int `json:"duration"`
StartedAt time.Time `json:"started_at"`
EndedAt *time.Time `json:"ended_at"`
}
)
func (c *Client) GetLatestPoll(ctx context.Context, username string) (*PollInfo, error) {
cacheKey := []string{"getLatestPoll", username}
if poll := c.apiCache.Get(cacheKey); poll != nil {
return poll.(*PollInfo), nil
}
id, err := c.GetIDForUsername(username)
if err != nil {
return nil, errors.Wrap(err, "getting ID for username")
}
var payload struct {
Data []*PollInfo `json:"data"`
}
if err := c.request(clientRequestOpts{
AuthType: authTypeBearerToken,
Context: ctx,
Method: http.MethodGet,
OKStatus: http.StatusOK,
Out: &payload,
URL: fmt.Sprintf("https://api.twitch.tv/helix/polls?broadcaster_id=%s&first=1", id),
}); err != nil {
return nil, errors.Wrap(err, "request channel info")
}
if len(payload.Data) < 1 {
return nil, errors.New("no polls found")
}
c.apiCache.Set(cacheKey, pollCacheTimeout, payload.Data[0])
return payload.Data[0], nil
}

View file

@ -218,6 +218,21 @@ Example:
< example string
```
#### `lastPoll`
Gets the last (currently running or archived) poll for the given channel (the channel must have given extended permission for poll access!)
Syntax: `lastPoll <channel>`
Example:
```
# Last Poll: {{ (lastPoll .channel).Title }}
< Last Poll: Und wie siehts im Template aus?
```
See schema of returned object in [`pkg/twitch/polls.go#L13`](https://github.com/Luzifer/twitch-bot/blob/master/pkg/twitch/polls.go#L13)
#### `lastQuoteIndex`
Gets the last quote index in the quote database for the current channel