mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-12-20 11:51:17 +00:00
[templating] Refactor: Move twitch functions into library package
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
a5df68d921
commit
220a501ab8
8 changed files with 327 additions and 255 deletions
|
@ -389,7 +389,7 @@ Example:
|
|||
|
||||
```
|
||||
# Your int this hour: {{ printf "%.0f" (mulf (seededRandom (list "int" .username (now | date "2006-01-02 15") | join ":")) 100) }}%
|
||||
< Your int this hour: 77%
|
||||
< Your int this hour: 46%
|
||||
```
|
||||
|
||||
### `streamUptime`
|
||||
|
|
|
@ -1,254 +0,0 @@
|
|||
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"
|
||||
)
|
||||
|
||||
//nolint:funlen
|
||||
func init() {
|
||||
tplFuncs.Register("displayName", plugins.GenericTemplateFunctionGetter(tplTwitchDisplayName), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns the display name the specified user set for themselves",
|
||||
Syntax: "displayName <username> [fallback]",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ displayName "luziferus" }} - {{ displayName "notexistinguser" "foobar" }}`,
|
||||
FakedOutput: "Luziferus - foobar",
|
||||
},
|
||||
})
|
||||
|
||||
tplFuncs.Register("doesFollowLongerThan", plugins.GenericTemplateFunctionGetter(tplTwitchDoesFollowLongerThan), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns whether `from` follows `to` for more than `duration`",
|
||||
Syntax: "doesFollowLongerThan <from> <to> <duration>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ doesFollowLongerThan "tezrian" "luziferus" "168h" }}`,
|
||||
FakedOutput: "true",
|
||||
},
|
||||
})
|
||||
|
||||
tplFuncs.Register("doesFollow", plugins.GenericTemplateFunctionGetter(tplTwitchDoesFollow), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns whether `from` follows `to`",
|
||||
Syntax: "doesFollow <from> <to>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ doesFollow "tezrian" "luziferus" }}`,
|
||||
FakedOutput: "true",
|
||||
},
|
||||
})
|
||||
|
||||
tplFuncs.Register("followAge", plugins.GenericTemplateFunctionGetter(tplTwitchFollowAge), plugins.TemplateFuncDocumentation{
|
||||
Description: "Looks up when `from` followed `to` and returns the duration between then and now",
|
||||
Syntax: "followAge <from> <to>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ followAge "tezrian" "luziferus" }}`,
|
||||
FakedOutput: "15004h14m59.116620989s",
|
||||
},
|
||||
})
|
||||
|
||||
tplFuncs.Register("followDate", plugins.GenericTemplateFunctionGetter(tplTwitchFollowDate), plugins.TemplateFuncDocumentation{
|
||||
Description: "Looks up when `from` followed `to`",
|
||||
Syntax: "followDate <from> <to>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ followDate "tezrian" "luziferus" }}`,
|
||||
FakedOutput: "2021-04-10 16:07:07 +0000 UTC",
|
||||
},
|
||||
})
|
||||
|
||||
tplFuncs.Register("idForUsername", plugins.GenericTemplateFunctionGetter(tplTwitchIDForUsername), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns the user-id for the given username",
|
||||
Syntax: "idForUsername <username>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ idForUsername "twitch" }}`,
|
||||
FakedOutput: "12826",
|
||||
},
|
||||
})
|
||||
|
||||
tplFuncs.Register("lastPoll", plugins.GenericTemplateFunctionGetter(tplTwitchLastPoll), plugins.TemplateFuncDocumentation{
|
||||
Description: "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: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `Last Poll: {{ (lastPoll .channel).Title }}`,
|
||||
FakedOutput: "Last Poll: Und wie siehts im Template aus?",
|
||||
},
|
||||
Remarks: "See schema of returned object in [`pkg/twitch/polls.go#L13`](https://github.com/Luzifer/twitch-bot/blob/master/pkg/twitch/polls.go#L13)",
|
||||
})
|
||||
|
||||
tplFuncs.Register("profileImage", plugins.GenericTemplateFunctionGetter(tplTwitchProfileImage), plugins.TemplateFuncDocumentation{
|
||||
Description: "Gets the URL of the given users profile image",
|
||||
Syntax: "profileImage <username>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ profileImage .username }}`,
|
||||
FakedOutput: "https://static-cdn.jtvnw.net/jtv_user_pictures/[...].png",
|
||||
},
|
||||
})
|
||||
|
||||
tplFuncs.Register("recentGame", plugins.GenericTemplateFunctionGetter(tplTwitchRecentGame), plugins.TemplateFuncDocumentation{
|
||||
Description: "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.",
|
||||
Syntax: "recentGame <username> [fallback]",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ recentGame "luziferus" "none" }} - {{ recentGame "thisuserdoesnotexist123" "none" }}`,
|
||||
FakedOutput: "Metro Exodus - none",
|
||||
},
|
||||
})
|
||||
|
||||
tplFuncs.Register("recentTitle", plugins.GenericTemplateFunctionGetter(tplTwitchRecentTitle), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns the last stream title of the specified user or the `fallback` if the title could not be fetched. If no fallback was supplied the message will fail and not be sent.",
|
||||
Syntax: "recentTitle <username> [fallback]",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ recentGame "luziferus" "none" }} - {{ recentGame "thisuserdoesnotexist123" "none" }}`,
|
||||
FakedOutput: "Die Oper haben wir überlebt, mal sehen was uns sonst noch alles töten möchte… - none",
|
||||
},
|
||||
})
|
||||
|
||||
tplFuncs.Register("streamUptime", plugins.GenericTemplateFunctionGetter(tplTwitchStreamUptime), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns the duration the stream is online (causes an error if no current stream is found)",
|
||||
Syntax: "streamUptime <username>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ formatDuration (streamUptime "luziferus") "hours" "minutes" "" }}`,
|
||||
FakedOutput: "3 hours, 56 minutes",
|
||||
},
|
||||
})
|
||||
|
||||
tplFuncs.Register("usernameForID", plugins.GenericTemplateFunctionGetter(tplTwitchUsernameForID), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns the current login name of an user-id",
|
||||
Syntax: "usernameForID <user-id>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ usernameForID "12826" }}`,
|
||||
FakedOutput: "twitch",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func tplTwitchDisplayName(username string, v ...string) (string, error) {
|
||||
displayName, err := twitchClient.GetDisplayNameForUser(strings.TrimLeft(username, "#"))
|
||||
if len(v) > 0 && (err != nil || displayName == "") {
|
||||
return v[0], nil //nolint:nilerr // Default value, no need to return error
|
||||
}
|
||||
|
||||
return displayName, err
|
||||
}
|
||||
|
||||
func tplTwitchDoesFollow(from, to string) (bool, error) {
|
||||
_, err := twitchClient.GetFollowDate(from, to)
|
||||
switch {
|
||||
case err == nil:
|
||||
return true, nil
|
||||
|
||||
case errors.Is(err, twitch.ErrUserDoesNotFollow):
|
||||
return false, nil
|
||||
|
||||
default:
|
||||
return false, errors.Wrap(err, "getting follow date")
|
||||
}
|
||||
}
|
||||
|
||||
func tplTwitchFollowAge(from, to string) (time.Duration, error) {
|
||||
since, err := twitchClient.GetFollowDate(from, to)
|
||||
return time.Since(since), errors.Wrap(err, "getting follow date")
|
||||
}
|
||||
|
||||
func tplTwitchFollowDate(from, to string) (time.Time, error) {
|
||||
return twitchClient.GetFollowDate(from, to)
|
||||
}
|
||||
|
||||
func tplTwitchDoesFollowLongerThan(from, to string, t any) (bool, error) {
|
||||
var (
|
||||
age time.Duration
|
||||
err error
|
||||
)
|
||||
|
||||
switch v := t.(type) {
|
||||
case int64:
|
||||
age = time.Duration(v) * time.Second
|
||||
|
||||
case string:
|
||||
if age, err = time.ParseDuration(v); err != nil {
|
||||
return false, errors.Wrap(err, "parsing duration")
|
||||
}
|
||||
|
||||
default:
|
||||
return false, errors.Errorf("unexpected input for duration %t", t)
|
||||
}
|
||||
|
||||
fd, err := twitchClient.GetFollowDate(from, to)
|
||||
switch {
|
||||
case err == nil:
|
||||
return time.Since(fd) > age, nil
|
||||
|
||||
case errors.Is(err, twitch.ErrUserDoesNotFollow):
|
||||
return false, nil
|
||||
|
||||
default:
|
||||
return false, errors.Wrap(err, "getting follow date")
|
||||
}
|
||||
}
|
||||
|
||||
func tplTwitchIDForUsername(username string) (string, error) {
|
||||
return twitchClient.GetIDForUsername(username)
|
||||
}
|
||||
|
||||
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 tplTwitchProfileImage(username string) (string, error) {
|
||||
user, err := twitchClient.GetUserInformation(strings.TrimLeft(username, "#@"))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "getting user info")
|
||||
}
|
||||
|
||||
return user.ProfileImageURL, nil
|
||||
}
|
||||
|
||||
func tplTwitchRecentGame(username string, v ...string) (string, error) {
|
||||
game, _, err := twitchClient.GetRecentStreamInfo(strings.TrimLeft(username, "#"))
|
||||
if len(v) > 0 && (err != nil || game == "") {
|
||||
return v[0], nil
|
||||
}
|
||||
|
||||
return game, err
|
||||
}
|
||||
|
||||
func tplTwitchRecentTitle(username string, v ...string) (string, error) {
|
||||
_, title, err := twitchClient.GetRecentStreamInfo(strings.TrimLeft(username, "#"))
|
||||
if len(v) > 0 && (err != nil || title == "") {
|
||||
return v[0], nil
|
||||
}
|
||||
|
||||
return title, err
|
||||
}
|
||||
|
||||
func tplTwitchStreamUptime(username string) (time.Duration, error) {
|
||||
si, err := twitchClient.GetCurrentStreamInfo(strings.TrimLeft(username, "#"))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return time.Since(si.StartedAt), nil
|
||||
}
|
||||
|
||||
func tplTwitchUsernameForID(id string) (string, error) {
|
||||
return twitchClient.GetUsernameForID(context.Background(), id)
|
||||
}
|
110
internal/template/twitch/follow.go
Normal file
110
internal/template/twitch/follow.go
Normal file
|
@ -0,0 +1,110 @@
|
|||
package twitch
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func init() {
|
||||
regFn = append(
|
||||
regFn,
|
||||
tplTwitchDoesFollow,
|
||||
tplTwitchDoesFollowLongerThan,
|
||||
tplTwitchFollowAge,
|
||||
tplTwitchFollowDate,
|
||||
)
|
||||
}
|
||||
|
||||
func tplTwitchDoesFollowLongerThan(args plugins.RegistrationArguments) {
|
||||
args.RegisterTemplateFunction("doesFollowLongerThan", plugins.GenericTemplateFunctionGetter(func(from, to string, t any) (bool, error) {
|
||||
var (
|
||||
age time.Duration
|
||||
err error
|
||||
)
|
||||
|
||||
switch v := t.(type) {
|
||||
case int64:
|
||||
age = time.Duration(v) * time.Second
|
||||
|
||||
case string:
|
||||
if age, err = time.ParseDuration(v); err != nil {
|
||||
return false, errors.Wrap(err, "parsing duration")
|
||||
}
|
||||
|
||||
default:
|
||||
return false, errors.Errorf("unexpected input for duration %t", t)
|
||||
}
|
||||
|
||||
fd, err := args.GetTwitchClient().GetFollowDate(from, to)
|
||||
switch {
|
||||
case err == nil:
|
||||
return time.Since(fd) > age, nil
|
||||
|
||||
case errors.Is(err, twitch.ErrUserDoesNotFollow):
|
||||
return false, nil
|
||||
|
||||
default:
|
||||
return false, errors.Wrap(err, "getting follow date")
|
||||
}
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns whether `from` follows `to` for more than `duration`",
|
||||
Syntax: "doesFollowLongerThan <from> <to> <duration>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ doesFollowLongerThan "tezrian" "luziferus" "168h" }}`,
|
||||
FakedOutput: "true",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func tplTwitchDoesFollow(args plugins.RegistrationArguments) {
|
||||
args.RegisterTemplateFunction("doesFollow", plugins.GenericTemplateFunctionGetter(func(from, to string) (bool, error) {
|
||||
_, err := args.GetTwitchClient().GetFollowDate(from, to)
|
||||
switch {
|
||||
case err == nil:
|
||||
return true, nil
|
||||
|
||||
case errors.Is(err, twitch.ErrUserDoesNotFollow):
|
||||
return false, nil
|
||||
|
||||
default:
|
||||
return false, errors.Wrap(err, "getting follow date")
|
||||
}
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns whether `from` follows `to`",
|
||||
Syntax: "doesFollow <from> <to>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ doesFollow "tezrian" "luziferus" }}`,
|
||||
FakedOutput: "true",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func tplTwitchFollowAge(args plugins.RegistrationArguments) {
|
||||
args.RegisterTemplateFunction("followAge", plugins.GenericTemplateFunctionGetter(func(from, to string) (time.Duration, error) {
|
||||
since, err := args.GetTwitchClient().GetFollowDate(from, to)
|
||||
return time.Since(since), errors.Wrap(err, "getting follow date")
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "Looks up when `from` followed `to` and returns the duration between then and now",
|
||||
Syntax: "followAge <from> <to>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ followAge "tezrian" "luziferus" }}`,
|
||||
FakedOutput: "15004h14m59.116620989s",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func tplTwitchFollowDate(args plugins.RegistrationArguments) {
|
||||
args.RegisterTemplateFunction("followDate", plugins.GenericTemplateFunctionGetter(func(from, to string) (time.Time, error) {
|
||||
return args.GetTwitchClient().GetFollowDate(from, to)
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "Looks up when `from` followed `to`",
|
||||
Syntax: "followDate <from> <to>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ followDate "tezrian" "luziferus" }}`,
|
||||
FakedOutput: "2021-04-10 16:07:07 +0000 UTC",
|
||||
},
|
||||
})
|
||||
}
|
46
internal/template/twitch/poll.go
Normal file
46
internal/template/twitch/poll.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
package twitch
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func init() {
|
||||
regFn = append(
|
||||
regFn,
|
||||
tplTwitchLastPoll,
|
||||
)
|
||||
}
|
||||
|
||||
func tplTwitchLastPoll(args plugins.RegistrationArguments) {
|
||||
args.RegisterTemplateFunction("lastPoll", plugins.GenericTemplateFunctionGetter(func(username string) (*twitch.PollInfo, error) {
|
||||
hasPollAccess, err := args.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 := args.GetTwitchClientForChannel(strings.TrimLeft(username, "#"))
|
||||
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")
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "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: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `Last Poll: {{ (lastPoll .channel).Title }}`,
|
||||
FakedOutput: "Last Poll: Und wie siehts im Template aus?",
|
||||
},
|
||||
Remarks: "See schema of returned object in [`pkg/twitch/polls.go#L13`](https://github.com/Luzifer/twitch-bot/blob/master/pkg/twitch/polls.go#L13)",
|
||||
})
|
||||
}
|
70
internal/template/twitch/stream.go
Normal file
70
internal/template/twitch/stream.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
package twitch
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
func init() {
|
||||
regFn = append(
|
||||
regFn,
|
||||
tplTwitchRecentGame,
|
||||
tplTwitchRecentTitle,
|
||||
tplTwitchStreamUptime,
|
||||
)
|
||||
}
|
||||
|
||||
func tplTwitchRecentGame(args plugins.RegistrationArguments) {
|
||||
args.RegisterTemplateFunction("recentGame", plugins.GenericTemplateFunctionGetter(func(username string, v ...string) (string, error) {
|
||||
game, _, err := args.GetTwitchClient().GetRecentStreamInfo(strings.TrimLeft(username, "#"))
|
||||
if len(v) > 0 && (err != nil || game == "") {
|
||||
return v[0], nil
|
||||
}
|
||||
|
||||
return game, err
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "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.",
|
||||
Syntax: "recentGame <username> [fallback]",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ recentGame "luziferus" "none" }} - {{ recentGame "thisuserdoesnotexist123" "none" }}`,
|
||||
FakedOutput: "Metro Exodus - none",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func tplTwitchRecentTitle(args plugins.RegistrationArguments) {
|
||||
args.RegisterTemplateFunction("recentTitle", plugins.GenericTemplateFunctionGetter(func(username string, v ...string) (string, error) {
|
||||
_, title, err := args.GetTwitchClient().GetRecentStreamInfo(strings.TrimLeft(username, "#"))
|
||||
if len(v) > 0 && (err != nil || title == "") {
|
||||
return v[0], nil
|
||||
}
|
||||
|
||||
return title, err
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns the last stream title of the specified user or the `fallback` if the title could not be fetched. If no fallback was supplied the message will fail and not be sent.",
|
||||
Syntax: "recentTitle <username> [fallback]",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ recentGame "luziferus" "none" }} - {{ recentGame "thisuserdoesnotexist123" "none" }}`,
|
||||
FakedOutput: "Die Oper haben wir überlebt, mal sehen was uns sonst noch alles töten möchte… - none",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func tplTwitchStreamUptime(args plugins.RegistrationArguments) {
|
||||
args.RegisterTemplateFunction("streamUptime", plugins.GenericTemplateFunctionGetter(func(username string) (time.Duration, error) {
|
||||
si, err := args.GetTwitchClient().GetCurrentStreamInfo(strings.TrimLeft(username, "#"))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return time.Since(si.StartedAt), nil
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns the duration the stream is online (causes an error if no current stream is found)",
|
||||
Syntax: "streamUptime <username>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ formatDuration (streamUptime "luziferus") "hours" "minutes" "" }}`,
|
||||
FakedOutput: "3 hours, 56 minutes",
|
||||
},
|
||||
})
|
||||
}
|
17
internal/template/twitch/twitch.go
Normal file
17
internal/template/twitch/twitch.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Package twitch defines Twitch related template functions not having
|
||||
// their place in any other package
|
||||
package twitch
|
||||
|
||||
import (
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
var regFn []func(plugins.RegistrationArguments)
|
||||
|
||||
func Register(args plugins.RegistrationArguments) error {
|
||||
for _, fn := range regFn {
|
||||
fn(args)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
81
internal/template/twitch/user.go
Normal file
81
internal/template/twitch/user.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
package twitch
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func init() {
|
||||
regFn = append(
|
||||
regFn,
|
||||
tplTwitchDisplayName,
|
||||
tplTwitchIDForUsername,
|
||||
tplTwitchProfileImage,
|
||||
tplTwitchUsernameForID,
|
||||
)
|
||||
}
|
||||
|
||||
func tplTwitchDisplayName(args plugins.RegistrationArguments) {
|
||||
args.RegisterTemplateFunction("displayName", plugins.GenericTemplateFunctionGetter(func(username string, v ...string) (string, error) {
|
||||
displayName, err := args.GetTwitchClient().GetDisplayNameForUser(strings.TrimLeft(username, "#"))
|
||||
if len(v) > 0 && (err != nil || displayName == "") {
|
||||
return v[0], nil //nolint:nilerr // Default value, no need to return error
|
||||
}
|
||||
|
||||
return displayName, err
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns the display name the specified user set for themselves",
|
||||
Syntax: "displayName <username> [fallback]",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ displayName "luziferus" }} - {{ displayName "notexistinguser" "foobar" }}`,
|
||||
FakedOutput: "Luziferus - foobar",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func tplTwitchIDForUsername(args plugins.RegistrationArguments) {
|
||||
args.RegisterTemplateFunction("idForUsername", plugins.GenericTemplateFunctionGetter(func(username string) (string, error) {
|
||||
return args.GetTwitchClient().GetIDForUsername(username)
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns the user-id for the given username",
|
||||
Syntax: "idForUsername <username>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ idForUsername "twitch" }}`,
|
||||
FakedOutput: "12826",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func tplTwitchProfileImage(args plugins.RegistrationArguments) {
|
||||
args.RegisterTemplateFunction("profileImage", plugins.GenericTemplateFunctionGetter(func(username string) (string, error) {
|
||||
user, err := args.GetTwitchClient().GetUserInformation(strings.TrimLeft(username, "#@"))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "getting user info")
|
||||
}
|
||||
|
||||
return user.ProfileImageURL, nil
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "Gets the URL of the given users profile image",
|
||||
Syntax: "profileImage <username>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ profileImage .username }}`,
|
||||
FakedOutput: "https://static-cdn.jtvnw.net/jtv_user_pictures/[...].png",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func tplTwitchUsernameForID(args plugins.RegistrationArguments) {
|
||||
args.RegisterTemplateFunction("usernameForID", plugins.GenericTemplateFunctionGetter(func(id string) (string, error) {
|
||||
return args.GetTwitchClient().GetUsernameForID(context.Background(), id)
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns the current login name of an user-id",
|
||||
Syntax: "usernameForID <user-id>",
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ usernameForID "12826" }}`,
|
||||
FakedOutput: "twitch",
|
||||
},
|
||||
})
|
||||
}
|
|
@ -48,6 +48,7 @@ import (
|
|||
"github.com/Luzifer/twitch-bot/v3/internal/template/slice"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/template/strings"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/template/subscriber"
|
||||
twitchFns "github.com/Luzifer/twitch-bot/v3/internal/template/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/twitch"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
|
@ -93,6 +94,7 @@ var (
|
|||
slice.Register,
|
||||
strings.Register,
|
||||
subscriber.Register,
|
||||
twitchFns.Register,
|
||||
|
||||
// API-only modules
|
||||
customevent.Register,
|
||||
|
|
Loading…
Reference in a new issue