mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-12-20 11:51:17 +00:00
[counter] Add counterRank
and counterTopList
template functions
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
a9e4931271
commit
ba21a372b5
4 changed files with 121 additions and 6 deletions
|
@ -100,6 +100,32 @@ Example:
|
|||
< #example:test
|
||||
```
|
||||
|
||||
### `counterRank`
|
||||
|
||||
Returns the rank of the given counter and the total number of counters in given counter prefix
|
||||
|
||||
Syntax: `counterRank <prefix> <name>`
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
# {{ $cr := counterRank (list .channel "test" "" | join ":") (list .channel "test" "foo" | join ":") }}{{ $cr.Rank }}/{{ $cr.Count }}
|
||||
* 2/6
|
||||
```
|
||||
|
||||
### `counterTopList`
|
||||
|
||||
Returns the top n counters for the given prefix as objects with Name and Value fields
|
||||
|
||||
Syntax: `counterTopList <prefix> <n>`
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
# {{ range (counterTopList (list .channel "test" "" | join ":") 3) }}{{ .Name }}: {{ .Value }} - {{ end }}
|
||||
* #example:test:foo: 5 - #example:test:bar: 4 -
|
||||
```
|
||||
|
||||
### `counterValue`
|
||||
|
||||
Returns the current value of the counter which identifier was supplied
|
||||
|
@ -389,7 +415,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: 11%
|
||||
< Your int this hour: 43%
|
||||
```
|
||||
|
||||
### `streamUptime`
|
||||
|
|
|
@ -24,7 +24,7 @@ var (
|
|||
//nolint:funlen // This function is a few lines too long but only contains definitions
|
||||
func Register(args plugins.RegistrationArguments) error {
|
||||
db = args.GetDatabaseConnector()
|
||||
if err := db.DB().AutoMigrate(&counter{}); err != nil {
|
||||
if err := db.DB().AutoMigrate(&Counter{}); err != nil {
|
||||
return errors.Wrap(err, "applying schema migration")
|
||||
}
|
||||
|
||||
|
@ -140,6 +140,29 @@ func Register(args plugins.RegistrationArguments) error {
|
|||
},
|
||||
})
|
||||
|
||||
args.RegisterTemplateFunction("counterRank", plugins.GenericTemplateFunctionGetter(func(prefix, name string) (res struct{ Rank, Count int64 }, err error) {
|
||||
res.Rank, res.Count, err = getCounterRank(db, prefix, name)
|
||||
return res, errors.Wrap(err, "getting counter rank")
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns the rank of the given counter and the total number of counters in given counter prefix",
|
||||
Syntax: `counterRank <prefix> <name>`,
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ $cr := counterRank (list .channel "test" "" | join ":") (list .channel "test" "foo" | join ":") }}{{ $cr.Rank }}/{{ $cr.Count }}`,
|
||||
FakedOutput: "2/6",
|
||||
},
|
||||
})
|
||||
|
||||
args.RegisterTemplateFunction("counterTopList", plugins.GenericTemplateFunctionGetter(func(prefix string, n int) ([]Counter, error) {
|
||||
return getCounterTopList(db, prefix, n)
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
Description: "Returns the top n counters for the given prefix as objects with Name and Value fields",
|
||||
Syntax: `counterTopList <prefix> <n>`,
|
||||
Example: &plugins.TemplateFuncDocumentationExample{
|
||||
Template: `{{ range (counterTopList (list .channel "test" "" | join ":") 3) }}{{ .Name }}: {{ .Value }} - {{ end }}`,
|
||||
FakedOutput: "#example:test:foo: 5 - #example:test:bar: 4 - ",
|
||||
},
|
||||
})
|
||||
|
||||
args.RegisterTemplateFunction("counterValue", plugins.GenericTemplateFunctionGetter(func(name string, _ ...string) (int64, error) {
|
||||
return GetCounterValue(db, name)
|
||||
}), plugins.TemplateFuncDocumentation{
|
||||
|
|
|
@ -9,14 +9,14 @@ import (
|
|||
)
|
||||
|
||||
type (
|
||||
counter struct {
|
||||
Counter struct {
|
||||
Name string `gorm:"primaryKey"`
|
||||
Value int64
|
||||
}
|
||||
)
|
||||
|
||||
func GetCounterValue(db database.Connector, counterName string) (int64, error) {
|
||||
var c counter
|
||||
var c Counter
|
||||
|
||||
err := db.DB().First(&c, "name = ?", counterName).Error
|
||||
switch {
|
||||
|
@ -45,7 +45,40 @@ func UpdateCounter(db database.Connector, counterName string, value int64, absol
|
|||
db.DB().Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "name"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"value"}),
|
||||
}).Create(counter{Name: counterName, Value: value}).Error,
|
||||
}).Create(Counter{Name: counterName, Value: value}).Error,
|
||||
"storing counter value",
|
||||
)
|
||||
}
|
||||
|
||||
func getCounterRank(db database.Connector, prefix, name string) (rank, count int64, err error) {
|
||||
var cc []Counter
|
||||
|
||||
err = db.DB().
|
||||
Order("value DESC").
|
||||
Find(&cc, "name LIKE ?", prefix+"%").
|
||||
Error
|
||||
if err != nil {
|
||||
return 0, 0, errors.Wrap(err, "querying counters")
|
||||
}
|
||||
|
||||
for i, c := range cc {
|
||||
count++
|
||||
if c.Name == name {
|
||||
rank = int64(i + 1)
|
||||
}
|
||||
}
|
||||
|
||||
return rank, count, nil
|
||||
}
|
||||
|
||||
func getCounterTopList(db database.Connector, prefix string, n int) ([]Counter, error) {
|
||||
var cc []Counter
|
||||
|
||||
err := db.DB().
|
||||
Order("value DESC").
|
||||
Limit(n).
|
||||
Find(&cc, "name LIKE ?", prefix+"%").
|
||||
Error
|
||||
|
||||
return cc, errors.Wrap(err, "querying counters")
|
||||
}
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
package counter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
||||
)
|
||||
|
||||
func TestCounterStoreLoop(t *testing.T) {
|
||||
dbc := database.GetTestDatabase(t)
|
||||
dbc.DB().AutoMigrate(&counter{})
|
||||
dbc.DB().AutoMigrate(&Counter{})
|
||||
|
||||
counterName := "mytestcounter"
|
||||
|
||||
|
@ -28,3 +30,34 @@ func TestCounterStoreLoop(t *testing.T) {
|
|||
assert.NoError(t, err, "reading existent counter")
|
||||
assert.Equal(t, int64(6), v, "expecting counter value on existing counter")
|
||||
}
|
||||
|
||||
func TestCounterTopListAndRank(t *testing.T) {
|
||||
dbc := database.GetTestDatabase(t)
|
||||
dbc.DB().AutoMigrate(&Counter{})
|
||||
|
||||
counterTemplate := `#example:test:%v`
|
||||
for i := 0; i < 6; i++ {
|
||||
require.NoError(
|
||||
t,
|
||||
UpdateCounter(dbc, fmt.Sprintf(counterTemplate, i), int64(i), true),
|
||||
"inserting counter %d", i,
|
||||
)
|
||||
}
|
||||
|
||||
cc, err := getCounterTopList(dbc, fmt.Sprintf(counterTemplate, ""), 3)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, cc, 3)
|
||||
|
||||
assert.Equal(t, []Counter{
|
||||
{Name: "#example:test:5", Value: 5},
|
||||
{Name: "#example:test:4", Value: 4},
|
||||
{Name: "#example:test:3", Value: 3},
|
||||
}, cc)
|
||||
|
||||
rank, count, err := getCounterRank(dbc,
|
||||
fmt.Sprintf(counterTemplate, ""),
|
||||
fmt.Sprintf(counterTemplate, 4))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(6), count)
|
||||
assert.Equal(t, int64(2), rank)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue