[template] Add subCount, subPoints template functions

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2023-04-22 22:23:35 +02:00
parent f562c2fec5
commit f9c6be800b
Signed by: luzifer
GPG key ID: D91C3E91E4CAD6F5
6 changed files with 142 additions and 5 deletions

View file

@ -0,0 +1,56 @@
package subscriber
import (
"context"
"strings"
"github.com/pkg/errors"
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
"github.com/Luzifer/twitch-bot/v3/plugins"
)
var (
permCheckFn plugins.ChannelPermissionCheckFunc
tcGetter func(string) (*twitch.Client, error)
)
func Register(args plugins.RegistrationArguments) error {
permCheckFn = args.HasPermissionForChannel
tcGetter = args.GetTwitchClientForChannel
args.RegisterTemplateFunction("subCount", plugins.GenericTemplateFunctionGetter(subCount))
args.RegisterTemplateFunction("subPoints", plugins.GenericTemplateFunctionGetter(subPoints))
return nil
}
func getSubInfo(broadcasterName string) (subCount, subPoints int64, err error) {
broadcasterName = strings.TrimLeft(broadcasterName, "#")
ok, err := permCheckFn(broadcasterName, twitch.ScopeChannelReadSubscriptions)
if err != nil {
return 0, 0, errors.Wrap(err, "checking for channel permissions")
}
if !ok {
return 0, 0, errors.Errorf("channel %q is missing permission %s", broadcasterName, twitch.ScopeChannelReadSubscriptions)
}
tc, err := tcGetter(broadcasterName)
if err != nil {
return 0, 0, errors.Wrap(err, "getting channel twitch-client")
}
sc, sp, err := tc.GetBroadcasterSubscriptionCount(context.Background(), broadcasterName)
return sc, sp, errors.Wrap(err, "fetching sub info")
}
func subCount(broadcasterName string) (int64, error) {
sc, _, err := getSubInfo(broadcasterName)
return sc, err
}
func subPoints(broadcasterName string) (int64, error) {
_, sp, err := getSubInfo(broadcasterName)
return sp, err
}

View file

@ -12,6 +12,7 @@ const (
ScopeChannelManageVIPS = "channel:manage:vips"
ScopeChannelManageWhispers = "user:manage:whispers"
ScopeChannelReadRedemptions = "channel:read:redemptions"
ScopeChannelReadSubscriptions = "channel:read:subscriptions"
ScopeModeratorManageAnnoucements = "moderator:manage:announcements"
ScopeModeratorManageBannedUsers = "moderator:manage:banned_users"
ScopeModeratorManageChatMessages = "moderator:manage:chat_messages"

View file

@ -0,0 +1,51 @@
package twitch
import (
"context"
"fmt"
"net/http"
"time"
"github.com/pkg/errors"
)
const subInfoCacheTimeout = 300 * time.Second
type (
subInfo struct {
Total int64 `json:"total"`
Points int64 `json:"points"`
}
)
// GetBroadcasterSubscriptionCount gets a list of users that subscribe to the specified broadcaster.
func (c *Client) GetBroadcasterSubscriptionCount(ctx context.Context, broadcasterName string) (subCount, subPoints int64, err error) {
cacheKey := []string{"broadcasterSubscriptionCountByChannel", broadcasterName}
if d := c.apiCache.Get(cacheKey); d != nil {
data := d.(subInfo)
return data.Total, data.Points, nil
}
broadcaster, err := c.GetIDForUsername(broadcasterName)
if err != nil {
return 0, 0, errors.Wrap(err, "getting ID for broadcaster name")
}
var data subInfo
if err = c.request(clientRequestOpts{
AuthType: authTypeBearerToken,
Context: ctx,
Method: http.MethodGet,
OKStatus: http.StatusOK,
Out: &data,
URL: fmt.Sprintf("https://api.twitch.tv/helix/subscriptions?broadcaster_id=%s", broadcaster),
}); err != nil {
return 0, 0, errors.Wrap(err, "executing request")
}
// Lets not annoy the API but only ask every 5m
c.apiCache.Set(cacheKey, subInfoCacheTimeout, data)
return data.Total, data.Points, nil
}

View file

@ -43,6 +43,7 @@ import (
"github.com/Luzifer/twitch-bot/v3/internal/template/numeric"
"github.com/Luzifer/twitch-bot/v3/internal/template/random"
"github.com/Luzifer/twitch-bot/v3/internal/template/slice"
"github.com/Luzifer/twitch-bot/v3/internal/template/subscriber"
"github.com/Luzifer/twitch-bot/v3/pkg/database"
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
"github.com/Luzifer/twitch-bot/v3/plugins"
@ -84,6 +85,7 @@ var (
numeric.Register,
random.Register,
slice.Register,
subscriber.Register,
// API-only modules
customevent.Register,

View file

@ -11,6 +11,7 @@ var (
twitch.ScopeChannelManageRaids: "start raids",
twitch.ScopeChannelManageVIPS: "manage VIPs",
twitch.ScopeChannelReadRedemptions: "see channel-point redemptions",
twitch.ScopeChannelReadSubscriptions: "see subscribed users / sub count / points",
twitch.ScopeModeratorReadFollowers: "see who follows this channel",
twitch.ScopeModeratorReadShoutouts: "see shoutouts created / received",
}

View file

@ -284,6 +284,19 @@ Example:
< Die Oper haben wir überlebt, mal sehen was uns sonst noch alles töten möchte - none
```
#### `seededRandom`
Returns a float value stable for the given seed
Syntax: `seededRandom <string-seed>`
Example:
```
# Your int this hour: {{ printf "%.0f" (multiply (seededRandom (list "int" .username (now "2006-01-02 15") | join ":")) 100) }}%
< Your int this hour: 17%
```
#### `streamUptime`
Returns the duration the stream is online (causes an error if no current stream is found)
@ -297,17 +310,30 @@ Example:
< 3 hours, 56 minutes
```
#### `seededRandom`
#### `subCount`
Returns a float value stable for the given seed
Returns the number of subscribers (accounts) currently subscribed to the given channel
Syntax: `seededRandom <string-seed>`
Syntax: `subCount <channel>`
Example:
```
# Your int this hour: {{ printf "%.0f" (multiply (seededRandom (list "int" .username (now "2006-01-02 15") | join ":")) 100) }}%
< Your int this hour: 17%
# {{ subCount "luziferus" }}
< 26
```
#### `subPoints`
Returns the number of sub-points currently given through the T1 / T2 / T3 subscriptions to the given channel
Syntax: `subPoints <channel>`
Example:
```
# {{ subPoints "luziferus" }}
< 26
```
#### `tag`