ergo/irc/batch.go

79 lines
2.0 KiB
Go

// Copyright (c) 2017 Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license
package irc
import (
"strconv"
"time"
"github.com/goshuirc/irc-go/ircmsg"
"github.com/oragono/oragono/irc/caps"
)
const (
// maxBatchID is the maximum ID the batch counter can get to before it rotates.
//
// Batch IDs are made up of the current unix timestamp plus a rolling int ID that's
// incremented for every new batch. It's an alright solution and will work unless we get
// more than maxId batches per nanosecond. Later on when we have S2S linking, the batch
// ID will also contain the server ID to ensure they stay unique.
maxBatchID uint64 = 60000
)
// BatchManager helps generate new batches and new batch IDs.
type BatchManager struct {
idCounter uint64
}
// NewBatchManager returns a new Manager.
func NewBatchManager() *BatchManager {
return &BatchManager{}
}
// NewID returns a new batch ID that should be unique.
func (bm *BatchManager) NewID() string {
bm.idCounter++
if maxBatchID < bm.idCounter {
bm.idCounter = 0
}
return strconv.FormatInt(time.Now().UnixNano(), 10) + strconv.FormatUint(bm.idCounter, 10)
}
// Batch represents an IRCv3 batch.
type Batch struct {
ID string
Type string
Params []string
}
// New returns a new batch.
func (bm *BatchManager) New(batchType string, params ...string) *Batch {
newBatch := Batch{
ID: bm.NewID(),
Type: batchType,
Params: params,
}
return &newBatch
}
// Start sends the batch start message to this client
func (b *Batch) Start(client *Client, tags *map[string]ircmsg.TagValue) {
if client.capabilities.Has(caps.Batch) {
params := []string{"+" + b.ID, b.Type}
for _, param := range b.Params {
params = append(params, param)
}
client.Send(tags, client.server.name, "BATCH", params...)
}
}
// End sends the batch end message to this client
func (b *Batch) End(client *Client) {
if client.capabilities.Has(caps.Batch) {
client.Send(nil, client.server.name, "BATCH", "-"+b.ID)
}
}