diff --git a/msgformatter.go b/msgformatter.go index 5e179c3..d0cd9c7 100644 --- a/msgformatter.go +++ b/msgformatter.go @@ -19,6 +19,7 @@ func formatMessage(tplString string, m *irc.Message, r *rule, fields map[string] // Generic functions messageFunctions["toLower"] = strings.ToLower messageFunctions["toUpper"] = strings.ToUpper + messageFunctions["followDate"] = twitch.GetFollowDate // Message specific functions messageFunctions["arg"] = func(arg int) (string, error) { @@ -43,7 +44,7 @@ func formatMessage(tplString string, m *irc.Message, r *rule, fields map[string] return store.GetCounterValue(name) } - messageFunctions["fixUsername"] = func(username string) string { return strings.TrimLeft(username, "@") } + messageFunctions["fixUsername"] = func(username string) string { return strings.TrimLeft(username, "@#") } messageFunctions["group"] = func(idx int) (string, error) { fields := r.matchMessage.FindStringSubmatch(m.Trailing()) diff --git a/twitch.go b/twitch.go index ba94142..c426b68 100644 --- a/twitch.go +++ b/twitch.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net/http" + "time" "github.com/pkg/errors" ) @@ -36,6 +37,42 @@ func (t twitchClient) getAuthorizedUsername() (string, error) { return payload.Data[0].Login, nil } +func (t twitchClient) GetFollowDate(from, to string) (time.Time, error) { + fromID, err := t.getIDForUsername(from) + if err != nil { + return time.Time{}, errors.Wrap(err, "getting id for 'from' user") + } + toID, err := t.getIDForUsername(to) + if err != nil { + return time.Time{}, errors.Wrap(err, "getting id for 'to' user") + } + + ctx, cancel := context.WithTimeout(context.Background(), twitchRequestTimeout) + defer cancel() + + var payload struct { + Data []struct { + FollowedAt time.Time `json:"followed_at"` + } `json:"data"` + } + + if err := t.request( + ctx, + http.MethodGet, + fmt.Sprintf("https://api.twitch.tv/helix/users/follows?to_id=%s&from_id=%s", toID, fromID), + nil, + &payload, + ); err != nil { + return time.Time{}, errors.Wrap(err, "request follow info") + } + + if l := len(payload.Data); l != 1 { + return time.Time{}, errors.Errorf("unexpected number of records returned: %d", l) + } + + return payload.Data[0].FollowedAt, nil +} + func (t twitchClient) getIDForUsername(username string) (string, error) { ctx, cancel := context.WithTimeout(context.Background(), twitchRequestTimeout) defer cancel() diff --git a/wiki/Home.md b/wiki/Home.md index 038b695..7f7a82c 100644 --- a/wiki/Home.md +++ b/wiki/Home.md @@ -79,7 +79,8 @@ 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 -- `fixUsername ` - Ensures the username no longer contains the `@` prefix +- `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 - `recentGame [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. - `tag ` - Takes the message sent to the channel, returns the value of the tag specified @@ -160,6 +161,15 @@ The example was dumped using this action: match_message: '(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]' ``` +### Post follow date for an user + +``` + - actions: + - respond: 'You followed on {{ ( followDate .username ( fixUsername .channel ) ).Format "2006-01-02" }}' + match_channels: ['#mychannel'] + match_message: '^!followage' +``` + ### Send a notification on successful permit ```yaml