diff --git a/functions_twitch.go b/functions_twitch.go index 13131b7..e5d3254 100644 --- a/functions_twitch.go +++ b/functions_twitch.go @@ -5,6 +5,15 @@ import ( ) func init() { + tplFuncs.Register("displayName", genericTemplateFunctionGetter(func(username string, v ...string) (string, error) { + displayName, err := twitch.GetDisplayNameForUser(strings.TrimLeft(username, "#")) + if err != nil && len(v) > 0 { + return v[0], nil + } + + return displayName, err + })) + tplFuncs.Register("recentGame", genericTemplateFunctionGetter(func(username string, v ...string) (string, error) { game, _, err := twitch.GetRecentStreamInfo(strings.TrimLeft(username, "#")) if err != nil && len(v) > 0 { diff --git a/twitch.go b/twitch.go index 108ee5e..5844d40 100644 --- a/twitch.go +++ b/twitch.go @@ -48,6 +48,43 @@ func (t twitchClient) getAuthorizedUsername() (string, error) { return payload.Data[0].Login, nil } +func (t twitchClient) GetDisplayNameForUser(username string) (string, error) { + cacheKey := []string{"displayNameForUsername", username} + if d := t.apiCache.Get(cacheKey); d != nil { + return d.(string), nil + } + + ctx, cancel := context.WithTimeout(context.Background(), twitchRequestTimeout) + defer cancel() + + var payload struct { + Data []struct { + ID string `json:"id"` + DisplayName string `json:"display_name"` + 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) + } + + // The DisplayName for an username will not change (often), cache for a decent time + t.apiCache.Set(cacheKey, time.Hour, payload.Data[0].DisplayName) + + return payload.Data[0].DisplayName, nil +} + func (t twitchClient) GetFollowDate(from, to string) (time.Time, error) { cacheKey := []string{"followDate", from, to} if d := t.apiCache.Get(cacheKey); d != nil { diff --git a/wiki/Home.md b/wiki/Home.md index 9a2dddd..ec1ee30 100644 --- a/wiki/Home.md +++ b/wiki/Home.md @@ -106,6 +106,7 @@ Additionally there are some functions available in the templates: - `arg ` - Takes the message sent to the channel, splits by space and returns the Nth element - `channelCounter ` - Wraps the counter name into a channel specific counter name including the channel name - `counterValue ` - Returns the current value of the counter which identifier was supplied +- `displayName [fallback]` - Returns the display name the specified user set for themselves - `fixUsername ` - Ensures the username no longer contains the `@` or `#` prefix - `followDate ` - Looks up when `from` followed `to` - `group ` - Gets matching group specified by index from `match_message` regular expression