Introduce Channel.{RelayDetached,ReattachOn,DetachAfter,DetachOn}

This adds several fields to the channel database schema and struct.
These fields will be used to add support for customizable message
relaying through BouncerServ, auto-reattaching, auto-detaching.

- RelayDetached is a filter for which notices to relay through
  BouncerServ for detached channels.
- ReattachOn is a filter for which messages to trigger a channel
  reattach on.
- DetachAfter is the duration after which to automatically detach a
  channel if no matching messages are received.
- DetachOn is a filter for which messages will reset the auto-detach
  timer.
This commit is contained in:
delthas 2020-11-30 22:01:44 +01:00 committed by Simon Ser
parent ddcaf558c0
commit 939c087754

58
db.go
View file

@ -3,8 +3,10 @@ package soju
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"math"
"strings" "strings"
"sync" "sync"
"time"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
) )
@ -52,11 +54,40 @@ func (net *Network) GetName() string {
return net.Addr return net.Addr
} }
type MessageFilter int
const (
// TODO: use customizable user defaults for FilterDefault
FilterDefault MessageFilter = iota
FilterNone
FilterHighlight
FilterMessage
)
func parseFilter(filter string) (MessageFilter, error) {
switch filter {
case "default":
return FilterDefault, nil
case "none":
return FilterNone, nil
case "highlight":
return FilterHighlight, nil
case "message":
return FilterMessage, nil
}
return 0, fmt.Errorf("unknown filter: %q", filter)
}
type Channel struct { type Channel struct {
ID int64 ID int64
Name string Name string
Key string Key string
Detached bool Detached bool
RelayDetached MessageFilter
ReattachOn MessageFilter
DetachAfter time.Duration
DetachOn MessageFilter
} }
const schema = ` const schema = `
@ -93,6 +124,10 @@ CREATE TABLE Channel (
name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL,
key VARCHAR(255), key VARCHAR(255),
detached INTEGER NOT NULL DEFAULT 0, detached INTEGER NOT NULL DEFAULT 0,
relay_detached INTEGER NOT NULL DEFAULT 0,
reattach_on INTEGER NOT NULL DEFAULT 0,
detach_after INTEGER NOT NULL DEFAULT 0,
detach_on INTEGER NOT NULL DEFAULT 0,
FOREIGN KEY(network) REFERENCES Network(id), FOREIGN KEY(network) REFERENCES Network(id),
UNIQUE(network, name) UNIQUE(network, name)
); );
@ -146,6 +181,12 @@ var migrations = []string{
DROP TABLE Network; DROP TABLE Network;
ALTER TABLE NetworkNew RENAME TO Network; ALTER TABLE NetworkNew RENAME TO Network;
`, `,
`
ALTER TABLE Channel ADD COLUMN relay_detached INTEGER NOT NULL DEFAULT 0;
ALTER TABLE Channel ADD COLUMN reattach_on INTEGER NOT NULL DEFAULT 0;
ALTER TABLE Channel ADD COLUMN detach_after INTEGER NOT NULL DEFAULT 0;
ALTER TABLE Channel ADD COLUMN detach_on INTEGER NOT NULL DEFAULT 0;
`,
} }
type DB struct { type DB struct {
@ -447,7 +488,7 @@ func (db *DB) ListChannels(networkID int64) ([]Channel, error) {
db.lock.RLock() db.lock.RLock()
defer db.lock.RUnlock() defer db.lock.RUnlock()
rows, err := db.db.Query(`SELECT id, name, key, detached rows, err := db.db.Query(`SELECT id, name, key, detached, relay_detached, reattach_on, detach_after, detach_on
FROM Channel FROM Channel
WHERE network = ?`, networkID) WHERE network = ?`, networkID)
if err != nil { if err != nil {
@ -459,10 +500,12 @@ func (db *DB) ListChannels(networkID int64) ([]Channel, error) {
for rows.Next() { for rows.Next() {
var ch Channel var ch Channel
var key sql.NullString var key sql.NullString
if err := rows.Scan(&ch.ID, &ch.Name, &key, &ch.Detached); err != nil { var detachAfter int64
if err := rows.Scan(&ch.ID, &ch.Name, &key, &ch.Detached, &ch.RelayDetached, &ch.ReattachOn, &detachAfter, &ch.DetachOn); err != nil {
return nil, err return nil, err
} }
ch.Key = key.String ch.Key = key.String
ch.DetachAfter = time.Duration(detachAfter) * time.Second
channels = append(channels, ch) channels = append(channels, ch)
} }
if err := rows.Err(); err != nil { if err := rows.Err(); err != nil {
@ -477,18 +520,19 @@ func (db *DB) StoreChannel(networkID int64, ch *Channel) error {
defer db.lock.Unlock() defer db.lock.Unlock()
key := toNullString(ch.Key) key := toNullString(ch.Key)
detachAfter := int64(math.Ceil(ch.DetachAfter.Seconds()))
var err error var err error
if ch.ID != 0 { if ch.ID != 0 {
_, err = db.db.Exec(`UPDATE Channel _, err = db.db.Exec(`UPDATE Channel
SET network = ?, name = ?, key = ?, detached = ? SET network = ?, name = ?, key = ?, detached = ?, relay_detached = ?, reattach_on = ?, detach_after = ?, detach_on = ?
WHERE id = ?`, WHERE id = ?`,
networkID, ch.Name, key, ch.Detached, ch.ID) networkID, ch.Name, key, ch.Detached, ch.RelayDetached, ch.ReattachOn, detachAfter, ch.DetachOn, ch.ID)
} else { } else {
var res sql.Result var res sql.Result
res, err = db.db.Exec(`INSERT INTO Channel(network, name, key, detached) res, err = db.db.Exec(`INSERT INTO Channel(network, name, key, detached, relay_detached, reattach_on, detach_after, detach_on)
VALUES (?, ?, ?, ?)`, VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
networkID, ch.Name, key, ch.Detached) networkID, ch.Name, key, ch.Detached, ch.RelayDetached, ch.ReattachOn, detachAfter, ch.DetachOn)
if err != nil { if err != nil {
return err return err
} }