mirror of
https://git.sr.ht/~ashkeel/strimertul
synced 2024-09-20 02:00:49 +00:00
refactor: use SyncSlice
This commit is contained in:
parent
330c4a3ec2
commit
db31c75662
8 changed files with 32 additions and 33 deletions
|
@ -27,7 +27,7 @@ Strimertül is a single executable app that provides the following:
|
||||||
|
|
||||||
At strimertül's core is [Kilovolt](https://github.com/strimertul/kilovolt), a pub/sub key-value store accessible via websocket. You can access every functionality of strimertul through the Kilovolt API. Check [this repository](https://github.com/strimertul/kilovolt-clients) for a list of officially supported kilovolt clients (or submit your own). You should be able to easily build a client yourself by just creating a websocket connection and using the [Kilovolt protocol](https://github.com/strimertul/kilovolt/blob/main/PROTOCOL.md).
|
At strimertül's core is [Kilovolt](https://github.com/strimertul/kilovolt), a pub/sub key-value store accessible via websocket. You can access every functionality of strimertul through the Kilovolt API. Check [this repository](https://github.com/strimertul/kilovolt-clients) for a list of officially supported kilovolt clients (or submit your own). You should be able to easily build a client yourself by just creating a websocket connection and using the [Kilovolt protocol](https://github.com/strimertul/kilovolt/blob/main/PROTOCOL.md).
|
||||||
|
|
||||||
Check out the [project's wiki](https://github.com/strimertul/strimertul/wiki) for more information on how to use the API to interact with strimertul, or the `docs` folder for more technical informations.
|
Check out the [project's wiki](https://github.com/strimertul/strimertul/wiki) for more information on how to use the API to interact with strimertul, or the `docs` folder for more technical information.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -3,7 +3,7 @@ module github.com/strimertul/strimertul
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.sr.ht/~hamcha/containers v0.2.1
|
git.sr.ht/~hamcha/containers v0.2.3
|
||||||
github.com/Masterminds/sprig/v3 v3.2.2
|
github.com/Masterminds/sprig/v3 v3.2.2
|
||||||
github.com/apenwarr/fixconsole v0.0.0-20191012055117-5a9f6489cc29
|
github.com/apenwarr/fixconsole v0.0.0-20191012055117-5a9f6489cc29
|
||||||
github.com/cockroachdb/pebble v0.0.0-20221116223310-87eccabb90a3
|
github.com/cockroachdb/pebble v0.0.0-20221116223310-87eccabb90a3
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -31,8 +31,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
git.sr.ht/~hamcha/containers v0.2.1 h1:mJ8b4fQhDKU73VRK1SjeIzJ5YnZYHeFHLJvHl6yKtNg=
|
git.sr.ht/~hamcha/containers v0.2.3 h1:h8BySrQg7bnOVC2a0WAs69Vkby6KYRPrsbTbdx/rrIE=
|
||||||
git.sr.ht/~hamcha/containers v0.2.1/go.mod h1:RiZphUpy9t6EnL4Gf6uzByM9QrBoqRCEPo7kz2wzbhE=
|
git.sr.ht/~hamcha/containers v0.2.3/go.mod h1:RiZphUpy9t6EnL4Gf6uzByM9QrBoqRCEPo7kz2wzbhE=
|
||||||
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
|
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
|
||||||
|
|
|
@ -17,12 +17,8 @@ type Config struct {
|
||||||
|
|
||||||
const RewardsKey = "loyalty/rewards"
|
const RewardsKey = "loyalty/rewards"
|
||||||
|
|
||||||
type RewardStorage []Reward
|
|
||||||
|
|
||||||
const GoalsKey = "loyalty/goals"
|
const GoalsKey = "loyalty/goals"
|
||||||
|
|
||||||
type GoalStorage []Goal
|
|
||||||
|
|
||||||
type Reward struct {
|
type Reward struct {
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
|
@ -53,8 +49,6 @@ type PointsEntry struct {
|
||||||
|
|
||||||
const QueueKey = "loyalty/redeem-queue"
|
const QueueKey = "loyalty/redeem-queue"
|
||||||
|
|
||||||
type RedeemQueueStorage []Redeem
|
|
||||||
|
|
||||||
type Redeem struct {
|
type Redeem struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
DisplayName string `json:"display_name"`
|
DisplayName string `json:"display_name"`
|
||||||
|
|
|
@ -30,9 +30,9 @@ var (
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
points *containers.SyncMap[string, PointsEntry]
|
points *containers.SyncMap[string, PointsEntry]
|
||||||
Config *containers.RWSync[Config]
|
Config *containers.RWSync[Config]
|
||||||
Rewards *containers.Sync[RewardStorage]
|
Rewards *containers.SyncSlice[Reward]
|
||||||
Goals *containers.Sync[GoalStorage]
|
Goals *containers.SyncSlice[Goal]
|
||||||
Queue *containers.Sync[RedeemQueueStorage]
|
Queue *containers.SyncSlice[Redeem]
|
||||||
db *database.LocalDBClient
|
db *database.LocalDBClient
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
cooldowns map[string]time.Time
|
cooldowns map[string]time.Time
|
||||||
|
@ -48,9 +48,9 @@ func NewManager(db *database.LocalDBClient, twitchManager *twitch.Manager, logge
|
||||||
ctx, cancelFn := context.WithCancel(context.Background())
|
ctx, cancelFn := context.WithCancel(context.Background())
|
||||||
loyalty := &Manager{
|
loyalty := &Manager{
|
||||||
Config: containers.NewRWSync(Config{Enabled: false}),
|
Config: containers.NewRWSync(Config{Enabled: false}),
|
||||||
Rewards: containers.NewSync(RewardStorage{}),
|
Rewards: containers.NewSyncSlice[Reward](),
|
||||||
Goals: containers.NewSync(GoalStorage{}),
|
Goals: containers.NewSyncSlice[Goal](),
|
||||||
Queue: containers.NewSync(RedeemQueueStorage{}),
|
Queue: containers.NewSyncSlice[Redeem](),
|
||||||
|
|
||||||
logger: logger,
|
logger: logger,
|
||||||
db: db,
|
db: db,
|
||||||
|
@ -73,7 +73,7 @@ func NewManager(db *database.LocalDBClient, twitchManager *twitch.Manager, logge
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve configs
|
// Retrieve configs
|
||||||
var rewards RewardStorage
|
var rewards []Reward
|
||||||
if err := db.GetJSON(RewardsKey, &rewards); err != nil {
|
if err := db.GetJSON(RewardsKey, &rewards); err != nil {
|
||||||
loyalty.Rewards.Set(rewards)
|
loyalty.Rewards.Set(rewards)
|
||||||
} else {
|
} else {
|
||||||
|
@ -82,7 +82,7 @@ func NewManager(db *database.LocalDBClient, twitchManager *twitch.Manager, logge
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var goals GoalStorage
|
var goals []Goal
|
||||||
if err := db.GetJSON(GoalsKey, &goals); err != nil {
|
if err := db.GetJSON(GoalsKey, &goals); err != nil {
|
||||||
loyalty.Goals.Set(goals)
|
loyalty.Goals.Set(goals)
|
||||||
} else {
|
} else {
|
||||||
|
@ -91,7 +91,7 @@ func NewManager(db *database.LocalDBClient, twitchManager *twitch.Manager, logge
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var queue RedeemQueueStorage
|
var queue []Redeem
|
||||||
if err := db.GetJSON(QueueKey, &queue); err != nil {
|
if err := db.GetJSON(QueueKey, &queue); err != nil {
|
||||||
loyalty.Queue.Set(queue)
|
loyalty.Queue.Set(queue)
|
||||||
} else {
|
} else {
|
||||||
|
@ -157,11 +157,11 @@ func (m *Manager) update(key, value string) {
|
||||||
m.SetBanList(m.Config.Get().BanList)
|
m.SetBanList(m.Config.Get().BanList)
|
||||||
}
|
}
|
||||||
case GoalsKey:
|
case GoalsKey:
|
||||||
err = utils.LoadJSONToWrapped[GoalStorage](value, m.Goals)
|
err = utils.LoadJSONToWrapped[[]Goal](value, m.Goals)
|
||||||
case RewardsKey:
|
case RewardsKey:
|
||||||
err = utils.LoadJSONToWrapped[RewardStorage](value, m.Rewards)
|
err = utils.LoadJSONToWrapped[[]Reward](value, m.Rewards)
|
||||||
case QueueKey:
|
case QueueKey:
|
||||||
err = utils.LoadJSONToWrapped[RedeemQueueStorage](value, m.Queue)
|
err = utils.LoadJSONToWrapped[[]Redeem](value, m.Queue)
|
||||||
case CreateRedeemRPC:
|
case CreateRedeemRPC:
|
||||||
var redeem Redeem
|
var redeem Redeem
|
||||||
err = json.UnmarshalFromString(value, &redeem)
|
err = json.UnmarshalFromString(value, &redeem)
|
||||||
|
|
|
@ -24,7 +24,7 @@ type Bot struct {
|
||||||
username string
|
username string
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
lastMessage *containers.RWSync[time.Time]
|
lastMessage *containers.RWSync[time.Time]
|
||||||
chatHistory *containers.Sync[[]irc.PrivateMessage]
|
chatHistory *containers.SyncSlice[irc.PrivateMessage]
|
||||||
|
|
||||||
commands *containers.SyncMap[string, BotCommand]
|
commands *containers.SyncMap[string, BotCommand]
|
||||||
customCommands *containers.SyncMap[string, BotCustomCommand]
|
customCommands *containers.SyncMap[string, BotCustomCommand]
|
||||||
|
@ -74,6 +74,7 @@ func newBot(api *Client, config BotConfig) *Bot {
|
||||||
commands: containers.NewSyncMap[string, BotCommand](),
|
commands: containers.NewSyncMap[string, BotCommand](),
|
||||||
customCommands: containers.NewSyncMap[string, BotCustomCommand](),
|
customCommands: containers.NewSyncMap[string, BotCustomCommand](),
|
||||||
customTemplates: containers.NewSyncMap[string, *template.Template](),
|
customTemplates: containers.NewSyncMap[string, *template.Template](),
|
||||||
|
chatHistory: containers.NewSyncSlice[irc.PrivateMessage](),
|
||||||
|
|
||||||
OnConnect: utils.NewPubSub[BotConnectHandler](),
|
OnConnect: utils.NewPubSub[BotConnectHandler](),
|
||||||
OnMessage: utils.NewPubSub[BotMessageHandler](),
|
OnMessage: utils.NewPubSub[BotMessageHandler](),
|
||||||
|
|
|
@ -34,7 +34,7 @@ type BotTimerModule struct {
|
||||||
|
|
||||||
bot *Bot
|
bot *Bot
|
||||||
lastTrigger *containers.SyncMap[string, time.Time]
|
lastTrigger *containers.SyncMap[string, time.Time]
|
||||||
messages *containers.RWSync[[AverageMessageWindow]int]
|
messages *containers.SyncSlice[int]
|
||||||
|
|
||||||
cancelTimerSub database.CancelFunc
|
cancelTimerSub database.CancelFunc
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,13 @@ func SetupTimers(bot *Bot) *BotTimerModule {
|
||||||
mod := &BotTimerModule{
|
mod := &BotTimerModule{
|
||||||
bot: bot,
|
bot: bot,
|
||||||
lastTrigger: containers.NewSyncMap[string, time.Time](),
|
lastTrigger: containers.NewSyncMap[string, time.Time](),
|
||||||
messages: containers.NewRWSync([AverageMessageWindow]int{}),
|
messages: containers.NewSyncSlice[int](),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill messages with zero values
|
||||||
|
// (This can probably be done faster)
|
||||||
|
for i := 0; i < AverageMessageWindow; i += 1 {
|
||||||
|
mod.messages.Push(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load config from database
|
// Load config from database
|
||||||
|
@ -160,7 +166,5 @@ func (m *BotTimerModule) currentChatActivity() int {
|
||||||
|
|
||||||
func (m *BotTimerModule) OnMessage(message irc.PrivateMessage) {
|
func (m *BotTimerModule) OnMessage(message irc.PrivateMessage) {
|
||||||
index := message.Time.Minute() % AverageMessageWindow
|
index := message.Time.Minute() % AverageMessageWindow
|
||||||
messages := m.messages.Get()
|
m.messages.SetIndex(index, 1)
|
||||||
messages[index] += 1
|
|
||||||
m.messages.Set(messages)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,21 @@ package utils
|
||||||
import "git.sr.ht/~hamcha/containers"
|
import "git.sr.ht/~hamcha/containers"
|
||||||
|
|
||||||
type PubSub[T Comparable] struct {
|
type PubSub[T Comparable] struct {
|
||||||
subscribers *containers.RWSync[[]T]
|
subscribers *containers.SyncSlice[T]
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPubSub[T Comparable]() *PubSub[T] {
|
func NewPubSub[T Comparable]() *PubSub[T] {
|
||||||
return &PubSub[T]{
|
return &PubSub[T]{
|
||||||
subscribers: containers.NewRWSync([]T{}),
|
subscribers: containers.NewSyncSlice[T](),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PubSub[T]) Subscribe(handler T) {
|
func (p *PubSub[T]) Subscribe(handler T) {
|
||||||
p.subscribers.Set(append(p.subscribers.Get(), handler))
|
p.subscribers.Push(handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PubSub[T]) Unsubscribe(handler T) {
|
func (p *PubSub[T]) Unsubscribe(handler T) {
|
||||||
arr := p.subscribers.Get()
|
arr := p.subscribers.Copy()
|
||||||
// Use slice trick to in-place remove entry if found
|
// Use slice trick to in-place remove entry if found
|
||||||
for index := range arr {
|
for index := range arr {
|
||||||
if arr[index].Equals(handler) {
|
if arr[index].Equals(handler) {
|
||||||
|
@ -29,7 +29,7 @@ func (p *PubSub[T]) Unsubscribe(handler T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PubSub[T]) Subscribers() []T {
|
func (p *PubSub[T]) Subscribers() []T {
|
||||||
return p.subscribers.Get()
|
return p.subscribers.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PubSub[T]) Copy(other *PubSub[T]) {
|
func (p *PubSub[T]) Copy(other *PubSub[T]) {
|
||||||
|
|
Loading…
Reference in a new issue