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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
@ -58,10 +59,33 @@ func init() {
|
||||||
tplFuncs.Register(n, plugins.GenericTemplateFunctionGetter(f))
|
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("toLower", plugins.GenericTemplateFunctionGetter(strings.ToLower))
|
||||||
tplFuncs.Register("toUpper", plugins.GenericTemplateFunctionGetter(strings.ToUpper))
|
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 {
|
tplFuncs.Register("variable", plugins.GenericTemplateFunctionGetter(func(name string, defVal ...string) string {
|
||||||
value := store.GetVariable(name)
|
value := store.GetVariable(name)
|
||||||
if value == "" && len(defVal) > 0 {
|
if value == "" && len(defVal) > 0 {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Luzifer/twitch-bot/plugins"
|
"github.com/Luzifer/twitch-bot/plugins"
|
||||||
)
|
)
|
||||||
|
@ -16,6 +17,8 @@ func init() {
|
||||||
return displayName, err
|
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) {
|
tplFuncs.Register("recentGame", plugins.GenericTemplateFunctionGetter(func(username string, v ...string) (string, error) {
|
||||||
game, _, err := twitchClient.GetRecentStreamInfo(strings.TrimLeft(username, "#"))
|
game, _, err := twitchClient.GetRecentStreamInfo(strings.TrimLeft(username, "#"))
|
||||||
if len(v) > 0 && (err != nil || game == "") {
|
if len(v) > 0 && (err != nil || game == "") {
|
||||||
|
@ -24,4 +27,12 @@ func init() {
|
||||||
|
|
||||||
return game, err
|
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
|
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 {
|
User struct {
|
||||||
DisplayName string `json:"display_name"`
|
DisplayName string `json:"display_name"`
|
||||||
ID string `json:"id"`
|
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
|
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) {
|
func (c Client) GetIDForUsername(username string) (string, error) {
|
||||||
cacheKey := []string{"idForUsername", username}
|
cacheKey := []string{"idForUsername", username}
|
||||||
if d := c.apiCache.Get(cacheKey); d != nil {
|
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
|
- `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
|
- `displayName <username> [fallback]` - Returns the display name the specified user set for themselves
|
||||||
- `fixUsername <username>` - Ensures the username no longer contains the `@` or `#` prefix
|
- `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`
|
- `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
|
- `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.
|
- `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
|
- `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
|
- `toLower <string>` - Converts the given string to lower-case
|
||||||
- `toUpper <string>` - Converts the given string to upper-case
|
- `toUpper <string>` - Converts the given string to upper-case
|
||||||
|
|
Loading…
Reference in a new issue