mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-11-09 16:50:01 +00:00
[counter] Allow counterTopList
to specify how to sort
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
94b040ed81
commit
293a7d9e30
4 changed files with 69 additions and 10 deletions
|
@ -128,9 +128,9 @@ Example:
|
||||||
|
|
||||||
### `counterTopList`
|
### `counterTopList`
|
||||||
|
|
||||||
Returns the top n counters for the given prefix as objects with Name and Value fields
|
Returns the top n counters for the given prefix as objects with Name and Value fields. Can be ordered by `name` / `value` / `first_seen` / `last_modified` ascending (`ASC`) or descending (`DESC`): i.e. `last_modified DESC` defaults to `value DESC`
|
||||||
|
|
||||||
Syntax: `counterTopList <prefix> <n>`
|
Syntax: `counterTopList <prefix> <n> [orderBy]`
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -467,7 +467,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: {{ printf "%.0f" (mulf (seededRandom (list "int" .username (now | date "2006-01-02 15") | join ":")) 100) }}%
|
||||||
< Your int this hour: 70%
|
< Your int this hour: 88%
|
||||||
```
|
```
|
||||||
|
|
||||||
### `spotifyCurrentPlaying`
|
### `spotifyCurrentPlaying`
|
||||||
|
|
|
@ -166,11 +166,11 @@ func Register(args plugins.RegistrationArguments) (err error) {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
args.RegisterTemplateFunction("counterTopList", plugins.GenericTemplateFunctionGetter(func(prefix string, n int) ([]counter, error) {
|
args.RegisterTemplateFunction("counterTopList", plugins.GenericTemplateFunctionGetter(func(prefix string, n int, orderBy string) ([]counter, error) {
|
||||||
return getCounterTopList(db, prefix, n)
|
return getCounterTopList(db, prefix, n, orderBy)
|
||||||
}), plugins.TemplateFuncDocumentation{
|
}), plugins.TemplateFuncDocumentation{
|
||||||
Description: "Returns the top n counters for the given prefix as objects with Name and Value fields",
|
Description: "Returns the top n counters for the given prefix as objects with Name and Value fields. Can be ordered by `name` / `value` / `first_seen` / `last_modified` ascending (`ASC`) or descending (`DESC`): i.e. `last_modified DESC` defaults to `value DESC`",
|
||||||
Syntax: `counterTopList <prefix> <n>`,
|
Syntax: `counterTopList <prefix> <n> [orderBy]`,
|
||||||
Example: &plugins.TemplateFuncDocumentationExample{
|
Example: &plugins.TemplateFuncDocumentationExample{
|
||||||
Template: `{{ range (counterTopList (list .channel "test" "" | join ":") 3) }}{{ .Name }}: {{ .Value }} - {{ end }}`,
|
Template: `{{ range (counterTopList (list .channel "test" "" | join ":") 3) }}{{ .Name }}: {{ .Value }} - {{ end }}`,
|
||||||
FakedOutput: "#example:test:foo: 5 - #example:test:bar: 4 - ",
|
FakedOutput: "#example:test:foo: 5 - #example:test:bar: 4 - ",
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
package counter
|
package counter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/clause"
|
"gorm.io/gorm/clause"
|
||||||
|
|
||||||
|
"github.com/Luzifer/go_helpers/v2/str"
|
||||||
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
|
||||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||||
)
|
)
|
||||||
|
@ -79,12 +82,39 @@ func getCounterRank(db database.Connector, prefix, name string) (rank, count int
|
||||||
return rank, count, nil
|
return rank, count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCounterTopList(db database.Connector, prefix string, n int) ([]counter, error) {
|
func getCounterTopList(db database.Connector, prefix string, n int, orderBy ...string) ([]counter, error) {
|
||||||
var cc []counter
|
var (
|
||||||
|
cc []counter
|
||||||
|
|
||||||
|
order string
|
||||||
|
validOrderCols = []string{"first_seen", "last_modified", "name", "value"}
|
||||||
|
validOrderDirs = []string{"ASC", "DESC"}
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(orderBy) == 0 || orderBy[0] == "" {
|
||||||
|
order = "value DESC"
|
||||||
|
} else {
|
||||||
|
order = orderBy[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
col, dir, _ := strings.Cut(order, " ")
|
||||||
|
if col == "" {
|
||||||
|
col = "value"
|
||||||
|
}
|
||||||
|
if dir == "" {
|
||||||
|
dir = "ASC"
|
||||||
|
}
|
||||||
|
|
||||||
|
if !str.StringInSlice(col, validOrderCols) {
|
||||||
|
return nil, fmt.Errorf("invalid orderBy column")
|
||||||
|
}
|
||||||
|
if !str.StringInSlice(dir, validOrderDirs) {
|
||||||
|
return nil, fmt.Errorf("invalid orderBy direction")
|
||||||
|
}
|
||||||
|
|
||||||
err := helpers.Retry(func() error {
|
err := helpers.Retry(func() error {
|
||||||
return db.DB().
|
return db.DB().
|
||||||
Order("value DESC").
|
Order(strings.Join([]string{col, dir}, " ")).
|
||||||
Limit(n).
|
Limit(n).
|
||||||
Find(&cc, "name LIKE ?", prefix+"%").
|
Find(&cc, "name LIKE ?", prefix+"%").
|
||||||
Error
|
Error
|
||||||
|
|
|
@ -64,6 +64,35 @@ func TestCounterTopListAndRank(t *testing.T) {
|
||||||
{Name: "#example:test:3", Value: 3, FirstSeen: testTime, LastModified: testTime},
|
{Name: "#example:test:3", Value: 3, FirstSeen: testTime, LastModified: testTime},
|
||||||
}, cc)
|
}, cc)
|
||||||
|
|
||||||
|
cc, err = getCounterTopList(dbc, fmt.Sprintf(counterTemplate, ""), 3, "name DESC")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, cc, 3)
|
||||||
|
|
||||||
|
assert.Equal(t, []counter{
|
||||||
|
{Name: "#example:test:5", Value: 5, FirstSeen: testTime, LastModified: testTime},
|
||||||
|
{Name: "#example:test:4", Value: 4, FirstSeen: testTime, LastModified: testTime},
|
||||||
|
{Name: "#example:test:3", Value: 3, FirstSeen: testTime, LastModified: testTime},
|
||||||
|
}, cc)
|
||||||
|
|
||||||
|
cc, err = getCounterTopList(dbc, fmt.Sprintf(counterTemplate, ""), 3, "name")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, cc, 3)
|
||||||
|
|
||||||
|
assert.Equal(t, []counter{
|
||||||
|
{Name: "#example:test:0", Value: 0, FirstSeen: testTime, LastModified: testTime},
|
||||||
|
{Name: "#example:test:1", Value: 1, FirstSeen: testTime, LastModified: testTime},
|
||||||
|
{Name: "#example:test:2", Value: 2, FirstSeen: testTime, LastModified: testTime},
|
||||||
|
}, cc)
|
||||||
|
|
||||||
|
_, err = getCounterTopList(dbc, fmt.Sprintf(counterTemplate, ""), 3, "foobar")
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
_, err = getCounterTopList(dbc, fmt.Sprintf(counterTemplate, ""), 3, "name foo")
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
_, err = getCounterTopList(dbc, fmt.Sprintf(counterTemplate, ""), 3, "name ASC; DROP TABLE counters;")
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
rank, count, err := getCounterRank(dbc,
|
rank, count, err := getCounterRank(dbc,
|
||||||
fmt.Sprintf(counterTemplate, ""),
|
fmt.Sprintf(counterTemplate, ""),
|
||||||
fmt.Sprintf(counterTemplate, 4))
|
fmt.Sprintf(counterTemplate, 4))
|
||||||
|
|
Loading…
Reference in a new issue