mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-12-20 20:01:17 +00:00
[core] add streamUptime / formatDuration template functions
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
87732995b3
commit
34d1f90540
4 changed files with 91 additions and 2 deletions
28
functions.go
28
functions.go
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/template"
|
||||
|
@ -58,10 +59,33 @@ func init() {
|
|||
tplFuncs.Register(n, plugins.GenericTemplateFunctionGetter(f))
|
||||
}
|
||||
|
||||
tplFuncs.Register("concat", plugins.GenericTemplateFunctionGetter(func(delim string, parts ...string) string { return strings.Join(parts, delim) }))
|
||||
|
||||
tplFuncs.Register("formatDuration", plugins.GenericTemplateFunctionGetter(func(dur time.Duration, units ...string) string {
|
||||
dLeft := dur
|
||||
|
||||
if len(units) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
var parts []string
|
||||
for idx, div := range []time.Duration{time.Hour, time.Minute, time.Second} {
|
||||
part := dLeft / div
|
||||
dLeft -= part * div
|
||||
|
||||
if len(units) <= idx || units[idx] == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
parts = append(parts, fmt.Sprintf("%d %s", part, units[idx]))
|
||||
}
|
||||
|
||||
return strings.Join(parts, ", ")
|
||||
}))
|
||||
|
||||
tplFuncs.Register("toLower", plugins.GenericTemplateFunctionGetter(strings.ToLower))
|
||||
tplFuncs.Register("toUpper", plugins.GenericTemplateFunctionGetter(strings.ToUpper))
|
||||
tplFuncs.Register("followDate", plugins.GenericTemplateFunctionGetter(func(from, to string) (time.Time, error) { return twitchClient.GetFollowDate(from, to) }))
|
||||
tplFuncs.Register("concat", plugins.GenericTemplateFunctionGetter(func(delim string, parts ...string) string { return strings.Join(parts, delim) }))
|
||||
|
||||
tplFuncs.Register("variable", plugins.GenericTemplateFunctionGetter(func(name string, defVal ...string) string {
|
||||
value := store.GetVariable(name)
|
||||
if value == "" && len(defVal) > 0 {
|
||||
|
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Luzifer/twitch-bot/plugins"
|
||||
)
|
||||
|
@ -16,6 +17,8 @@ func init() {
|
|||
return displayName, err
|
||||
}))
|
||||
|
||||
tplFuncs.Register("followDate", plugins.GenericTemplateFunctionGetter(func(from, to string) (time.Time, error) { return twitchClient.GetFollowDate(from, to) }))
|
||||
|
||||
tplFuncs.Register("recentGame", plugins.GenericTemplateFunctionGetter(func(username string, v ...string) (string, error) {
|
||||
game, _, err := twitchClient.GetRecentStreamInfo(strings.TrimLeft(username, "#"))
|
||||
if len(v) > 0 && (err != nil || game == "") {
|
||||
|
@ -24,4 +27,12 @@ func init() {
|
|||
|
||||
return game, err
|
||||
}))
|
||||
|
||||
tplFuncs.Register("streamUptime", plugins.GenericTemplateFunctionGetter(func(username string) (time.Duration, error) {
|
||||
si, err := twitchClient.GetCurrentStreamInfo(strings.TrimLeft(username, "#"))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return time.Since(si.StartedAt), nil
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -39,6 +39,23 @@ type (
|
|||
apiCache *APICache
|
||||
}
|
||||
|
||||
StreamInfo struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"user_id"`
|
||||
UserLogin string `json:"user_login"`
|
||||
UserName string `json:"user_name"`
|
||||
GameID string `json:"game_id"`
|
||||
GameName string `json:"game_name"`
|
||||
Type string `json:"type"`
|
||||
Title string `json:"title"`
|
||||
ViewerCount int64 `json:"viewer_count"`
|
||||
StartedAt time.Time `json:"started_at"`
|
||||
Language string `json:"language"`
|
||||
ThumbnailURL string `json:"thumbnail_url"`
|
||||
TagIds []string `json:"tag_ids"`
|
||||
IsMature bool `json:"is_mature"`
|
||||
}
|
||||
|
||||
User struct {
|
||||
DisplayName string `json:"display_name"`
|
||||
ID string `json:"id"`
|
||||
|
@ -253,6 +270,41 @@ func (c Client) HasLiveStream(username string) (bool, error) {
|
|||
return len(payload.Data) == 1 && payload.Data[0].Type == "live", nil
|
||||
}
|
||||
|
||||
func (c Client) GetCurrentStreamInfo(username string) (*StreamInfo, error) {
|
||||
cacheKey := []string{"currentStreamInfo", username}
|
||||
if si := c.apiCache.Get(cacheKey); si != nil {
|
||||
return si.(*StreamInfo), nil
|
||||
}
|
||||
|
||||
id, err := c.GetIDForUsername(username)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting ID for username")
|
||||
}
|
||||
|
||||
var payload struct {
|
||||
Data []*StreamInfo `json:"data"`
|
||||
}
|
||||
|
||||
if err := c.request(
|
||||
context.Background(),
|
||||
http.MethodGet,
|
||||
fmt.Sprintf("https://api.twitch.tv/helix/streams?user_id=%s", id),
|
||||
nil,
|
||||
&payload,
|
||||
); err != nil {
|
||||
return nil, errors.Wrap(err, "request channel info")
|
||||
}
|
||||
|
||||
if l := len(payload.Data); l != 1 {
|
||||
return nil, errors.Errorf("unexpected number of users returned: %d", l)
|
||||
}
|
||||
|
||||
// Stream-info can be changed at any moment, cache for a short period of time
|
||||
c.apiCache.Set(cacheKey, twitchMinCacheTime, payload.Data[0])
|
||||
|
||||
return payload.Data[0], nil
|
||||
}
|
||||
|
||||
func (c Client) GetIDForUsername(username string) (string, error) {
|
||||
cacheKey := []string{"idForUsername", username}
|
||||
if d := c.apiCache.Get(cacheKey); d != nil {
|
||||
|
|
|
@ -137,9 +137,11 @@ Additionally there are some functions available in the templates:
|
|||
- `counterValue <counter name>` - Returns the current value of the counter which identifier was supplied
|
||||
- `displayName <username> [fallback]` - Returns the display name the specified user set for themselves
|
||||
- `fixUsername <username>` - Ensures the username no longer contains the `@` or `#` prefix
|
||||
- `formatDuration <duration> <hours> <minutes> <seconds>` - Returns a formated duration. Pass empty strings to leave out the part: `{{ formatDuration .dur "hours" "minutes" "" }}` yields `N hours, M minutes`
|
||||
- `followDate <from> <to>` - Looks up when `from` followed `to`
|
||||
- `group <idx> [fallback]` - Gets matching group specified by index from `match_message` regular expression, when `fallback` is defined, it is used when group has an empty match
|
||||
- `recentGame <username> [fallback]` - Returns the last played game name of the specified user (see shoutout example) or the `fallback` if the game could not be fetched. If no fallback was supplied the message will fail and not be sent.
|
||||
- `streamUptime <username>` - Returns the duration the stream is online (causes an error if no current stream is found)
|
||||
- `tag <tagname>` - Takes the message sent to the channel, returns the value of the tag specified
|
||||
- `toLower <string>` - Converts the given string to lower-case
|
||||
- `toUpper <string>` - Converts the given string to upper-case
|
||||
|
|
Loading…
Reference in a new issue