Handle kick, rename server to network
This commit is contained in:
parent
a33157ff84
commit
6985dd16da
65 changed files with 2650 additions and 2179 deletions
|
@ -48,8 +48,8 @@ func (b *Bleve) Index(id string, message *storage.Message) error {
|
|||
return b.index.Index(id, message)
|
||||
}
|
||||
|
||||
func (b *Bleve) SearchMessages(server, channel, q string) ([]string, error) {
|
||||
serverQuery := bleve.NewMatchQuery(server)
|
||||
func (b *Bleve) SearchMessages(network, channel, q string) ([]string, error) {
|
||||
serverQuery := bleve.NewMatchQuery(network)
|
||||
serverQuery.SetField("server")
|
||||
channelQuery := bleve.NewMatchQuery(channel)
|
||||
channelQuery.SetField("to")
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
|
||||
var (
|
||||
bucketUsers = []byte("Users")
|
||||
bucketServers = []byte("Servers")
|
||||
bucketNetworks = []byte("Networks")
|
||||
bucketChannels = []byte("Channels")
|
||||
bucketOpenDMs = []byte("OpenDMs")
|
||||
bucketMessages = []byte("Messages")
|
||||
|
@ -33,7 +33,7 @@ func New(path string) (*BoltStore, error) {
|
|||
|
||||
db.Update(func(tx *bolt.Tx) error {
|
||||
tx.CreateBucketIfNotExists(bucketUsers)
|
||||
tx.CreateBucketIfNotExists(bucketServers)
|
||||
tx.CreateBucketIfNotExists(bucketNetworks)
|
||||
tx.CreateBucketIfNotExists(bucketChannels)
|
||||
tx.CreateBucketIfNotExists(bucketOpenDMs)
|
||||
tx.CreateBucketIfNotExists(bucketMessages)
|
||||
|
@ -50,7 +50,7 @@ func (s *BoltStore) Close() {
|
|||
s.db.Close()
|
||||
}
|
||||
|
||||
func (s *BoltStore) GetUsers() ([]*storage.User, error) {
|
||||
func (s *BoltStore) Users() ([]*storage.User, error) {
|
||||
var users []*storage.User
|
||||
|
||||
s.db.View(func(tx *bolt.Tx) error {
|
||||
|
@ -99,69 +99,69 @@ func (s *BoltStore) DeleteUser(user *storage.User) error {
|
|||
}
|
||||
|
||||
return deletePrefix(user.IDBytes,
|
||||
tx.Bucket(bucketServers),
|
||||
tx.Bucket(bucketNetworks),
|
||||
tx.Bucket(bucketChannels),
|
||||
tx.Bucket(bucketOpenDMs),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BoltStore) GetServer(user *storage.User, address string) (*storage.Server, error) {
|
||||
var server *storage.Server
|
||||
func (s *BoltStore) Network(user *storage.User, address string) (*storage.Network, error) {
|
||||
var network *storage.Network
|
||||
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketServers)
|
||||
id := serverID(user, address)
|
||||
b := tx.Bucket(bucketNetworks)
|
||||
id := networkID(user, address)
|
||||
|
||||
v := b.Get(id)
|
||||
if v == nil {
|
||||
return storage.ErrNotFound
|
||||
} else {
|
||||
server = &storage.Server{}
|
||||
server.Unmarshal(v)
|
||||
network = &storage.Network{}
|
||||
network.Unmarshal(v)
|
||||
return nil
|
||||
}
|
||||
})
|
||||
|
||||
return server, err
|
||||
return network, err
|
||||
}
|
||||
|
||||
func (s *BoltStore) GetServers(user *storage.User) ([]*storage.Server, error) {
|
||||
var servers []*storage.Server
|
||||
func (s *BoltStore) Networks(user *storage.User) ([]*storage.Network, error) {
|
||||
var networks []*storage.Network
|
||||
|
||||
s.db.View(func(tx *bolt.Tx) error {
|
||||
c := tx.Bucket(bucketServers).Cursor()
|
||||
c := tx.Bucket(bucketNetworks).Cursor()
|
||||
|
||||
for k, v := c.Seek(user.IDBytes); bytes.HasPrefix(k, user.IDBytes); k, v = c.Next() {
|
||||
server := storage.Server{}
|
||||
server.Unmarshal(v)
|
||||
servers = append(servers, &server)
|
||||
network := storage.Network{}
|
||||
network.Unmarshal(v)
|
||||
networks = append(networks, &network)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return servers, nil
|
||||
return networks, nil
|
||||
}
|
||||
|
||||
func (s *BoltStore) SaveServer(user *storage.User, server *storage.Server) error {
|
||||
func (s *BoltStore) SaveNetwork(user *storage.User, network *storage.Network) error {
|
||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketServers)
|
||||
data, _ := server.Marshal(nil)
|
||||
b := tx.Bucket(bucketNetworks)
|
||||
data, _ := network.Marshal(nil)
|
||||
|
||||
return b.Put(serverID(user, server.Host), data)
|
||||
return b.Put(networkID(user, network.Host), data)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BoltStore) RemoveServer(user *storage.User, address string) error {
|
||||
func (s *BoltStore) RemoveNetwork(user *storage.User, address string) error {
|
||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
||||
serverID := serverID(user, address)
|
||||
err := tx.Bucket(bucketServers).Delete(serverID)
|
||||
networkID := networkID(user, address)
|
||||
err := tx.Bucket(bucketNetworks).Delete(networkID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return deletePrefix(serverID,
|
||||
return deletePrefix(networkID,
|
||||
tx.Bucket(bucketChannels),
|
||||
tx.Bucket(bucketOpenDMs),
|
||||
)
|
||||
|
@ -170,16 +170,16 @@ func (s *BoltStore) RemoveServer(user *storage.User, address string) error {
|
|||
|
||||
func (s *BoltStore) SetNick(user *storage.User, nick, address string) error {
|
||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketServers)
|
||||
id := serverID(user, address)
|
||||
b := tx.Bucket(bucketNetworks)
|
||||
id := networkID(user, address)
|
||||
|
||||
server := storage.Server{}
|
||||
network := storage.Network{}
|
||||
v := b.Get(id)
|
||||
if v != nil {
|
||||
server.Unmarshal(v)
|
||||
server.Nick = nick
|
||||
network.Unmarshal(v)
|
||||
network.Nick = nick
|
||||
|
||||
data, _ := server.Marshal(nil)
|
||||
data, _ := network.Marshal(nil)
|
||||
return b.Put(id, data)
|
||||
}
|
||||
|
||||
|
@ -187,18 +187,18 @@ func (s *BoltStore) SetNick(user *storage.User, nick, address string) error {
|
|||
})
|
||||
}
|
||||
|
||||
func (s *BoltStore) SetServerName(user *storage.User, name, address string) error {
|
||||
func (s *BoltStore) SetNetworkName(user *storage.User, name, address string) error {
|
||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketServers)
|
||||
id := serverID(user, address)
|
||||
b := tx.Bucket(bucketNetworks)
|
||||
id := networkID(user, address)
|
||||
|
||||
server := storage.Server{}
|
||||
network := storage.Network{}
|
||||
v := b.Get(id)
|
||||
if v != nil {
|
||||
server.Unmarshal(v)
|
||||
server.Name = name
|
||||
network.Unmarshal(v)
|
||||
network.Name = name
|
||||
|
||||
data, _ := server.Marshal(nil)
|
||||
data, _ := network.Marshal(nil)
|
||||
return b.Put(id, data)
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,7 @@ func (s *BoltStore) SetServerName(user *storage.User, name, address string) erro
|
|||
})
|
||||
}
|
||||
|
||||
func (s *BoltStore) GetChannels(user *storage.User) ([]*storage.Channel, error) {
|
||||
func (s *BoltStore) Channels(user *storage.User) ([]*storage.Channel, error) {
|
||||
var channels []*storage.Channel
|
||||
|
||||
s.db.View(func(tx *bolt.Tx) error {
|
||||
|
@ -224,25 +224,36 @@ func (s *BoltStore) GetChannels(user *storage.User) ([]*storage.Channel, error)
|
|||
return channels, nil
|
||||
}
|
||||
|
||||
func (s *BoltStore) AddChannel(user *storage.User, channel *storage.Channel) error {
|
||||
func (s *BoltStore) SaveChannel(user *storage.User, channel *storage.Channel) error {
|
||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketChannels)
|
||||
data, _ := channel.Marshal(nil)
|
||||
|
||||
return b.Put(channelID(user, channel.Server, channel.Name), data)
|
||||
return b.Put(channelID(user, channel.Network, channel.Name), data)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BoltStore) RemoveChannel(user *storage.User, server, channel string) error {
|
||||
func (s *BoltStore) RemoveChannel(user *storage.User, network, channel string) error {
|
||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketChannels)
|
||||
id := channelID(user, server, channel)
|
||||
id := channelID(user, network, channel)
|
||||
|
||||
return b.Delete(id)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BoltStore) GetOpenDMs(user *storage.User) ([]storage.Tab, error) {
|
||||
func (s *BoltStore) HasChannel(user *storage.User, network, channel string) bool {
|
||||
has := false
|
||||
s.db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketChannels)
|
||||
has = b.Get(channelID(user, network, channel)) != nil
|
||||
|
||||
return nil
|
||||
})
|
||||
return has
|
||||
}
|
||||
|
||||
func (s *BoltStore) OpenDMs(user *storage.User) ([]storage.Tab, error) {
|
||||
var openDMs []storage.Tab
|
||||
|
||||
s.db.View(func(tx *bolt.Tx) error {
|
||||
|
@ -251,8 +262,8 @@ func (s *BoltStore) GetOpenDMs(user *storage.User) ([]storage.Tab, error) {
|
|||
for k, _ := c.Seek(user.IDBytes); bytes.HasPrefix(k, user.IDBytes); k, _ = c.Next() {
|
||||
tab := bytes.Split(k[8:], []byte{0})
|
||||
openDMs = append(openDMs, storage.Tab{
|
||||
Server: string(tab[0]),
|
||||
Name: string(tab[1]),
|
||||
Network: string(tab[0]),
|
||||
Name: string(tab[1]),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -262,24 +273,24 @@ func (s *BoltStore) GetOpenDMs(user *storage.User) ([]storage.Tab, error) {
|
|||
return openDMs, nil
|
||||
}
|
||||
|
||||
func (s *BoltStore) AddOpenDM(user *storage.User, server, nick string) error {
|
||||
func (s *BoltStore) AddOpenDM(user *storage.User, network, nick string) error {
|
||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketOpenDMs)
|
||||
|
||||
return b.Put(channelID(user, server, nick), nil)
|
||||
return b.Put(channelID(user, network, nick), nil)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BoltStore) RemoveOpenDM(user *storage.User, server, nick string) error {
|
||||
func (s *BoltStore) RemoveOpenDM(user *storage.User, network, nick string) error {
|
||||
return s.db.Batch(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketOpenDMs)
|
||||
|
||||
return b.Delete(channelID(user, server, nick))
|
||||
return b.Delete(channelID(user, network, nick))
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BoltStore) logMessage(tx *bolt.Tx, message *storage.Message) error {
|
||||
b, err := tx.Bucket(bucketMessages).CreateBucketIfNotExists([]byte(message.Server + ":" + message.To))
|
||||
b, err := tx.Bucket(bucketMessages).CreateBucketIfNotExists([]byte(message.Network + ":" + message.To))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -311,12 +322,12 @@ func (s *BoltStore) LogMessages(messages []*storage.Message) error {
|
|||
})
|
||||
}
|
||||
|
||||
func (s *BoltStore) GetMessages(server, channel string, count int, fromID string) ([]storage.Message, bool, error) {
|
||||
func (s *BoltStore) Messages(network, channel string, count int, fromID string) ([]storage.Message, bool, error) {
|
||||
messages := make([]storage.Message, count)
|
||||
hasMore := false
|
||||
|
||||
s.db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketMessages).Bucket([]byte(server + ":" + channel))
|
||||
b := tx.Bucket(bucketMessages).Bucket([]byte(network + ":" + channel))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -353,11 +364,11 @@ func (s *BoltStore) GetMessages(server, channel string, count int, fromID string
|
|||
return nil, false, nil
|
||||
}
|
||||
|
||||
func (s *BoltStore) GetMessagesByID(server, channel string, ids []string) ([]storage.Message, error) {
|
||||
func (s *BoltStore) MessagesByID(network, channel string, ids []string) ([]storage.Message, error) {
|
||||
messages := make([]storage.Message, len(ids))
|
||||
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucketMessages).Bucket([]byte(server + ":" + channel))
|
||||
b := tx.Bucket(bucketMessages).Bucket([]byte(network + ":" + channel))
|
||||
|
||||
for i, id := range ids {
|
||||
messages[i].Unmarshal(b.Get([]byte(id)))
|
||||
|
@ -367,7 +378,7 @@ func (s *BoltStore) GetMessagesByID(server, channel string, ids []string) ([]sto
|
|||
return messages, err
|
||||
}
|
||||
|
||||
func (s *BoltStore) GetSessions() ([]*session.Session, error) {
|
||||
func (s *BoltStore) Sessions() ([]*session.Session, error) {
|
||||
var sessions []*session.Session
|
||||
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
|
@ -422,18 +433,18 @@ func deletePrefix(prefix []byte, buckets ...*bolt.Bucket) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func serverID(user *storage.User, address string) []byte {
|
||||
func networkID(user *storage.User, address string) []byte {
|
||||
id := make([]byte, 8+len(address))
|
||||
copy(id, user.IDBytes)
|
||||
copy(id[8:], address)
|
||||
return id
|
||||
}
|
||||
|
||||
func channelID(user *storage.User, server, channel string) []byte {
|
||||
id := make([]byte, 8+len(server)+1+len(channel))
|
||||
func channelID(user *storage.User, network, channel string) []byte {
|
||||
id := make([]byte, 8+len(network)+1+len(channel))
|
||||
copy(id, user.IDBytes)
|
||||
copy(id[8:], server)
|
||||
copy(id[8+len(server)+1:], channel)
|
||||
copy(id[8:], network)
|
||||
copy(id[8+len(network)+1:], channel)
|
||||
return id
|
||||
}
|
||||
|
||||
|
|
|
@ -124,32 +124,32 @@ type managedChannelIndex struct {
|
|||
updating bool
|
||||
}
|
||||
|
||||
func (m *ChannelIndexManager) Get(server string) (ChannelListIndex, bool) {
|
||||
func (m *ChannelIndexManager) Get(network string) (ChannelListIndex, bool) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
idx, ok := m.indexes[server]
|
||||
idx, ok := m.indexes[network]
|
||||
if !ok {
|
||||
m.indexes[server] = &managedChannelIndex{
|
||||
m.indexes[network] = &managedChannelIndex{
|
||||
updating: true,
|
||||
}
|
||||
go m.timeoutUpdate(server)
|
||||
go m.timeoutUpdate(network)
|
||||
return nil, true
|
||||
}
|
||||
|
||||
if !idx.updating && time.Since(idx.updatedAt) > ChannelListUpdateInterval {
|
||||
idx.updating = true
|
||||
go m.timeoutUpdate(server)
|
||||
go m.timeoutUpdate(network)
|
||||
return idx.index, true
|
||||
}
|
||||
|
||||
return idx.index, false
|
||||
}
|
||||
|
||||
func (m *ChannelIndexManager) Set(server string, index ChannelListIndex) {
|
||||
func (m *ChannelIndexManager) Set(network string, index ChannelListIndex) {
|
||||
if index.len() > 0 {
|
||||
m.lock.Lock()
|
||||
m.indexes[server] = &managedChannelIndex{
|
||||
m.indexes[network] = &managedChannelIndex{
|
||||
index: index,
|
||||
updatedAt: time.Now(),
|
||||
}
|
||||
|
@ -157,12 +157,12 @@ func (m *ChannelIndexManager) Set(server string, index ChannelListIndex) {
|
|||
}
|
||||
}
|
||||
|
||||
func (m *ChannelIndexManager) timeoutUpdate(server string) {
|
||||
func (m *ChannelIndexManager) timeoutUpdate(network string) {
|
||||
time.Sleep(ChannelListUpdateTimeout)
|
||||
|
||||
m.lock.Lock()
|
||||
if m.indexes[server].updating {
|
||||
m.indexes[server].updating = false
|
||||
if m.indexes[network].updating {
|
||||
m.indexes[network].updating = false
|
||||
}
|
||||
m.lock.Unlock()
|
||||
}
|
||||
|
|
216
storage/network.go
Normal file
216
storage/network.go
Normal file
|
@ -0,0 +1,216 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/khlieng/dispatch/pkg/irc"
|
||||
"github.com/khlieng/dispatch/version"
|
||||
)
|
||||
|
||||
type Network struct {
|
||||
Name string
|
||||
Host string
|
||||
Port string
|
||||
TLS bool
|
||||
ServerPassword string
|
||||
Nick string
|
||||
Username string
|
||||
Realname string
|
||||
Account string
|
||||
Password string
|
||||
|
||||
Features map[string]interface{}
|
||||
Connected bool
|
||||
Error string
|
||||
|
||||
user *User
|
||||
client *irc.Client
|
||||
channels map[string]*Channel
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
func (n *Network) Save() error {
|
||||
return n.user.SaveNetwork(n.Copy())
|
||||
}
|
||||
|
||||
func (n *Network) Copy() *Network {
|
||||
n.lock.Lock()
|
||||
network := Network{
|
||||
Name: n.Name,
|
||||
Host: n.Host,
|
||||
Port: n.Port,
|
||||
TLS: n.TLS,
|
||||
ServerPassword: n.ServerPassword,
|
||||
Nick: n.Nick,
|
||||
Username: n.Username,
|
||||
Realname: n.Realname,
|
||||
Account: n.Account,
|
||||
Password: n.Password,
|
||||
Features: n.Features,
|
||||
Connected: n.Connected,
|
||||
Error: n.Error,
|
||||
user: n.user,
|
||||
client: n.client,
|
||||
channels: n.channels,
|
||||
}
|
||||
n.lock.Unlock()
|
||||
|
||||
return &network
|
||||
}
|
||||
|
||||
func (n *Network) Client() *irc.Client {
|
||||
return n.client
|
||||
}
|
||||
|
||||
func (n *Network) IRCConfig() *irc.Config {
|
||||
return &irc.Config{
|
||||
Host: n.Host,
|
||||
Port: n.Port,
|
||||
TLS: n.TLS,
|
||||
Nick: n.Nick,
|
||||
Username: n.Username,
|
||||
Realname: n.Realname,
|
||||
Account: n.Account,
|
||||
Password: n.Password,
|
||||
Version: fmt.Sprintf("Dispatch %s (git: %s)", version.Tag, version.Commit),
|
||||
Source: "https://github.com/khlieng/dispatch",
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Network) SetName(name string) {
|
||||
n.lock.Lock()
|
||||
n.Name = name
|
||||
n.lock.Unlock()
|
||||
}
|
||||
|
||||
func (n *Network) SetNick(nick string) {
|
||||
n.lock.Lock()
|
||||
n.Nick = nick
|
||||
n.lock.Unlock()
|
||||
}
|
||||
|
||||
func (n *Network) SetFeatures(features map[string]interface{}) {
|
||||
n.lock.Lock()
|
||||
n.Features = features
|
||||
n.lock.Unlock()
|
||||
}
|
||||
|
||||
func (n *Network) SetStatus(connected bool, err string) {
|
||||
n.lock.Lock()
|
||||
n.Connected = connected
|
||||
n.Error = err
|
||||
n.lock.Unlock()
|
||||
}
|
||||
|
||||
func (n *Network) Channel(name string) *Channel {
|
||||
n.lock.Lock()
|
||||
ch := n.channels[name]
|
||||
n.lock.Unlock()
|
||||
return ch
|
||||
}
|
||||
|
||||
func (n *Network) Channels() []*Channel {
|
||||
n.lock.Lock()
|
||||
channels := make([]*Channel, 0, len(n.channels))
|
||||
for _, ch := range n.channels {
|
||||
channels = append(channels, ch.Copy())
|
||||
}
|
||||
n.lock.Unlock()
|
||||
|
||||
return channels
|
||||
}
|
||||
|
||||
func (n *Network) ChannelNames() []string {
|
||||
n.lock.Lock()
|
||||
names := make([]string, 0, len(n.channels))
|
||||
for _, ch := range n.channels {
|
||||
names = append(names, ch.Name)
|
||||
}
|
||||
n.lock.Unlock()
|
||||
|
||||
return names
|
||||
}
|
||||
|
||||
func (n *Network) NewChannel(name string) *Channel {
|
||||
return &Channel{
|
||||
Network: n.Host,
|
||||
Name: name,
|
||||
user: n.user,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Network) AddChannel(channel *Channel) {
|
||||
n.lock.Lock()
|
||||
n.channels[channel.Name] = channel
|
||||
n.lock.Unlock()
|
||||
}
|
||||
|
||||
func (n *Network) RemoveChannels(channels ...string) {
|
||||
n.lock.Lock()
|
||||
for _, name := range channels {
|
||||
delete(n.channels, name)
|
||||
}
|
||||
n.lock.Unlock()
|
||||
}
|
||||
|
||||
type Channel struct {
|
||||
Network string
|
||||
Name string
|
||||
|
||||
Topic string
|
||||
Joined bool
|
||||
|
||||
user *User
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
func (c *Channel) Save() error {
|
||||
return c.user.SaveChannel(c.Copy())
|
||||
}
|
||||
|
||||
func (c *Channel) Copy() *Channel {
|
||||
c.lock.Lock()
|
||||
ch := Channel{
|
||||
Network: c.Network,
|
||||
Name: c.Name,
|
||||
Topic: c.Topic,
|
||||
Joined: c.Joined,
|
||||
user: c.user,
|
||||
}
|
||||
c.lock.Unlock()
|
||||
|
||||
return &ch
|
||||
}
|
||||
|
||||
func (c *Channel) SetTopic(topic string) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.lock.Lock()
|
||||
c.Topic = topic
|
||||
c.lock.Unlock()
|
||||
}
|
||||
|
||||
func (c *Channel) IsJoined() bool {
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
c.lock.Lock()
|
||||
joined := c.Joined
|
||||
c.lock.Unlock()
|
||||
|
||||
return joined
|
||||
}
|
||||
|
||||
func (c *Channel) SetJoined(joined bool) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.lock.Lock()
|
||||
c.Joined = joined
|
||||
c.lock.Unlock()
|
||||
}
|
377
storage/network_easyjson.go
Normal file
377
storage/network_easyjson.go
Normal file
|
@ -0,0 +1,377 @@
|
|||
//v1: false// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.
|
||||
|
||||
package storage
|
||||
|
||||
import (
|
||||
json "encoding/json"
|
||||
easyjson "github.com/mailru/easyjson"
|
||||
jlexer "github.com/mailru/easyjson/jlexer"
|
||||
jwriter "github.com/mailru/easyjson/jwriter"
|
||||
)
|
||||
|
||||
// suppress unused package warning
|
||||
var (
|
||||
_ *json.RawMessage
|
||||
_ *jlexer.Lexer
|
||||
_ *jwriter.Writer
|
||||
_ easyjson.Marshaler
|
||||
)
|
||||
|
||||
func easyjsonC5839400DecodeGithubComKhliengDispatchStorage(in *jlexer.Lexer, out *Network) {
|
||||
isTopLevel := in.IsStart()
|
||||
if in.IsNull() {
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
in.Skip()
|
||||
return
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
in.WantComma()
|
||||
continue
|
||||
}
|
||||
switch key {
|
||||
case "name":
|
||||
out.Name = string(in.String())
|
||||
case "host":
|
||||
out.Host = string(in.String())
|
||||
case "port":
|
||||
out.Port = string(in.String())
|
||||
case "tls":
|
||||
out.TLS = bool(in.Bool())
|
||||
case "serverPassword":
|
||||
out.ServerPassword = string(in.String())
|
||||
case "nick":
|
||||
out.Nick = string(in.String())
|
||||
case "username":
|
||||
out.Username = string(in.String())
|
||||
case "realname":
|
||||
out.Realname = string(in.String())
|
||||
case "account":
|
||||
out.Account = string(in.String())
|
||||
case "password":
|
||||
out.Password = string(in.String())
|
||||
case "features":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
in.Delim('{')
|
||||
if !in.IsDelim('}') {
|
||||
out.Features = make(map[string]interface{})
|
||||
} else {
|
||||
out.Features = nil
|
||||
}
|
||||
for !in.IsDelim('}') {
|
||||
key := string(in.String())
|
||||
in.WantColon()
|
||||
var v1 interface{}
|
||||
if m, ok := v1.(easyjson.Unmarshaler); ok {
|
||||
m.UnmarshalEasyJSON(in)
|
||||
} else if m, ok := v1.(json.Unmarshaler); ok {
|
||||
_ = m.UnmarshalJSON(in.Raw())
|
||||
} else {
|
||||
v1 = in.Interface()
|
||||
}
|
||||
(out.Features)[key] = v1
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
}
|
||||
case "connected":
|
||||
out.Connected = bool(in.Bool())
|
||||
case "error":
|
||||
out.Error = string(in.String())
|
||||
default:
|
||||
in.SkipRecursive()
|
||||
}
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
}
|
||||
func easyjsonC5839400EncodeGithubComKhliengDispatchStorage(out *jwriter.Writer, in Network) {
|
||||
out.RawByte('{')
|
||||
first := true
|
||||
_ = first
|
||||
if in.Name != "" {
|
||||
const prefix string = ",\"name\":"
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
out.String(string(in.Name))
|
||||
}
|
||||
if in.Host != "" {
|
||||
const prefix string = ",\"host\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.String(string(in.Host))
|
||||
}
|
||||
if in.Port != "" {
|
||||
const prefix string = ",\"port\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.String(string(in.Port))
|
||||
}
|
||||
if in.TLS {
|
||||
const prefix string = ",\"tls\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.Bool(bool(in.TLS))
|
||||
}
|
||||
if in.ServerPassword != "" {
|
||||
const prefix string = ",\"serverPassword\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.String(string(in.ServerPassword))
|
||||
}
|
||||
if in.Nick != "" {
|
||||
const prefix string = ",\"nick\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.String(string(in.Nick))
|
||||
}
|
||||
if in.Username != "" {
|
||||
const prefix string = ",\"username\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.String(string(in.Username))
|
||||
}
|
||||
if in.Realname != "" {
|
||||
const prefix string = ",\"realname\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.String(string(in.Realname))
|
||||
}
|
||||
if in.Account != "" {
|
||||
const prefix string = ",\"account\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.String(string(in.Account))
|
||||
}
|
||||
if in.Password != "" {
|
||||
const prefix string = ",\"password\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.String(string(in.Password))
|
||||
}
|
||||
if len(in.Features) != 0 {
|
||||
const prefix string = ",\"features\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
{
|
||||
out.RawByte('{')
|
||||
v2First := true
|
||||
for v2Name, v2Value := range in.Features {
|
||||
if v2First {
|
||||
v2First = false
|
||||
} else {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v2Name))
|
||||
out.RawByte(':')
|
||||
if m, ok := v2Value.(easyjson.Marshaler); ok {
|
||||
m.MarshalEasyJSON(out)
|
||||
} else if m, ok := v2Value.(json.Marshaler); ok {
|
||||
out.Raw(m.MarshalJSON())
|
||||
} else {
|
||||
out.Raw(json.Marshal(v2Value))
|
||||
}
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
||||
}
|
||||
if in.Connected {
|
||||
const prefix string = ",\"connected\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.Bool(bool(in.Connected))
|
||||
}
|
||||
if in.Error != "" {
|
||||
const prefix string = ",\"error\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.String(string(in.Error))
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
||||
|
||||
// MarshalJSON supports json.Marshaler interface
|
||||
func (v Network) MarshalJSON() ([]byte, error) {
|
||||
w := jwriter.Writer{}
|
||||
easyjsonC5839400EncodeGithubComKhliengDispatchStorage(&w, v)
|
||||
return w.Buffer.BuildBytes(), w.Error
|
||||
}
|
||||
|
||||
// MarshalEasyJSON supports easyjson.Marshaler interface
|
||||
func (v Network) MarshalEasyJSON(w *jwriter.Writer) {
|
||||
easyjsonC5839400EncodeGithubComKhliengDispatchStorage(w, v)
|
||||
}
|
||||
|
||||
// UnmarshalJSON supports json.Unmarshaler interface
|
||||
func (v *Network) UnmarshalJSON(data []byte) error {
|
||||
r := jlexer.Lexer{Data: data}
|
||||
easyjsonC5839400DecodeGithubComKhliengDispatchStorage(&r, v)
|
||||
return r.Error()
|
||||
}
|
||||
|
||||
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
|
||||
func (v *Network) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
||||
easyjsonC5839400DecodeGithubComKhliengDispatchStorage(l, v)
|
||||
}
|
||||
func easyjsonC5839400DecodeGithubComKhliengDispatchStorage1(in *jlexer.Lexer, out *Channel) {
|
||||
isTopLevel := in.IsStart()
|
||||
if in.IsNull() {
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
in.Skip()
|
||||
return
|
||||
}
|
||||
in.Delim('{')
|
||||
for !in.IsDelim('}') {
|
||||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
in.WantComma()
|
||||
continue
|
||||
}
|
||||
switch key {
|
||||
case "network":
|
||||
out.Network = string(in.String())
|
||||
case "name":
|
||||
out.Name = string(in.String())
|
||||
case "topic":
|
||||
out.Topic = string(in.String())
|
||||
case "joined":
|
||||
out.Joined = bool(in.Bool())
|
||||
default:
|
||||
in.SkipRecursive()
|
||||
}
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
if isTopLevel {
|
||||
in.Consumed()
|
||||
}
|
||||
}
|
||||
func easyjsonC5839400EncodeGithubComKhliengDispatchStorage1(out *jwriter.Writer, in Channel) {
|
||||
out.RawByte('{')
|
||||
first := true
|
||||
_ = first
|
||||
if in.Network != "" {
|
||||
const prefix string = ",\"network\":"
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
out.String(string(in.Network))
|
||||
}
|
||||
if in.Name != "" {
|
||||
const prefix string = ",\"name\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.String(string(in.Name))
|
||||
}
|
||||
if in.Topic != "" {
|
||||
const prefix string = ",\"topic\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.String(string(in.Topic))
|
||||
}
|
||||
if in.Joined {
|
||||
const prefix string = ",\"joined\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
out.Bool(bool(in.Joined))
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
||||
|
||||
// MarshalJSON supports json.Marshaler interface
|
||||
func (v Channel) MarshalJSON() ([]byte, error) {
|
||||
w := jwriter.Writer{}
|
||||
easyjsonC5839400EncodeGithubComKhliengDispatchStorage1(&w, v)
|
||||
return w.Buffer.BuildBytes(), w.Error
|
||||
}
|
||||
|
||||
// MarshalEasyJSON supports easyjson.Marshaler interface
|
||||
func (v Channel) MarshalEasyJSON(w *jwriter.Writer) {
|
||||
easyjsonC5839400EncodeGithubComKhliengDispatchStorage1(w, v)
|
||||
}
|
||||
|
||||
// UnmarshalJSON supports json.Unmarshaler interface
|
||||
func (v *Channel) UnmarshalJSON(data []byte) error {
|
||||
r := jlexer.Lexer{Data: data}
|
||||
easyjsonC5839400DecodeGithubComKhliengDispatchStorage1(&r, v)
|
||||
return r.Error()
|
||||
}
|
||||
|
||||
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
|
||||
func (v *Channel) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
||||
easyjsonC5839400DecodeGithubComKhliengDispatchStorage1(l, v)
|
||||
}
|
|
@ -31,26 +31,27 @@ var (
|
|||
)
|
||||
|
||||
type Store interface {
|
||||
GetUsers() ([]*User, error)
|
||||
Users() ([]*User, error)
|
||||
SaveUser(user *User) error
|
||||
DeleteUser(user *User) error
|
||||
|
||||
GetServer(user *User, host string) (*Server, error)
|
||||
GetServers(user *User) ([]*Server, error)
|
||||
SaveServer(user *User, server *Server) error
|
||||
RemoveServer(user *User, host string) error
|
||||
Network(user *User, host string) (*Network, error)
|
||||
Networks(user *User) ([]*Network, error)
|
||||
SaveNetwork(user *User, network *Network) error
|
||||
RemoveNetwork(user *User, host string) error
|
||||
|
||||
GetChannels(user *User) ([]*Channel, error)
|
||||
AddChannel(user *User, channel *Channel) error
|
||||
RemoveChannel(user *User, server, channel string) error
|
||||
Channels(user *User) ([]*Channel, error)
|
||||
HasChannel(user *User, network, channel string) bool
|
||||
SaveChannel(user *User, channel *Channel) error
|
||||
RemoveChannel(user *User, network, channel string) error
|
||||
|
||||
GetOpenDMs(user *User) ([]Tab, error)
|
||||
AddOpenDM(user *User, server, nick string) error
|
||||
RemoveOpenDM(user *User, server, nick string) error
|
||||
OpenDMs(user *User) ([]Tab, error)
|
||||
AddOpenDM(user *User, network, nick string) error
|
||||
RemoveOpenDM(user *User, network, nick string) error
|
||||
}
|
||||
|
||||
type SessionStore interface {
|
||||
GetSessions() ([]*session.Session, error)
|
||||
Sessions() ([]*session.Session, error)
|
||||
SaveSession(session *session.Session) error
|
||||
DeleteSession(key string) error
|
||||
}
|
||||
|
@ -58,15 +59,15 @@ type SessionStore interface {
|
|||
type MessageStore interface {
|
||||
LogMessage(message *Message) error
|
||||
LogMessages(messages []*Message) error
|
||||
GetMessages(server, channel string, count int, fromID string) ([]Message, bool, error)
|
||||
GetMessagesByID(server, channel string, ids []string) ([]Message, error)
|
||||
Messages(network, channel string, count int, fromID string) ([]Message, bool, error)
|
||||
MessagesByID(network, channel string, ids []string) ([]Message, error)
|
||||
Close()
|
||||
}
|
||||
|
||||
type MessageStoreCreator func(*User) (MessageStore, error)
|
||||
|
||||
type MessageSearchProvider interface {
|
||||
SearchMessages(server, channel, q string) ([]string, error)
|
||||
SearchMessages(network, channel, q string) ([]string, error)
|
||||
Index(id string, message *Message) error
|
||||
Close()
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ struct ClientSettings {
|
|||
ColoredNicks bool
|
||||
}
|
||||
|
||||
struct Server {
|
||||
struct Network {
|
||||
Name string
|
||||
Host string
|
||||
Port string
|
||||
|
@ -23,7 +23,7 @@ struct Server {
|
|||
}
|
||||
|
||||
struct Channel {
|
||||
Server string
|
||||
Network string
|
||||
Name string
|
||||
}
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ func (d *ClientSettings) Unmarshal(buf []byte) (uint64, error) {
|
|||
return i + 1, nil
|
||||
}
|
||||
|
||||
func (d *Server) Size() (s uint64) {
|
||||
func (d *Network) Size() (s uint64) {
|
||||
|
||||
{
|
||||
l := uint64(len(d.Name))
|
||||
|
@ -378,7 +378,7 @@ func (d *Server) Size() (s uint64) {
|
|||
s += 1
|
||||
return
|
||||
}
|
||||
func (d *Server) Marshal(buf []byte) ([]byte, error) {
|
||||
func (d *Network) Marshal(buf []byte) ([]byte, error) {
|
||||
size := d.Size()
|
||||
{
|
||||
if uint64(cap(buf)) >= size {
|
||||
|
@ -570,7 +570,7 @@ func (d *Server) Marshal(buf []byte) ([]byte, error) {
|
|||
return buf[:i+1], nil
|
||||
}
|
||||
|
||||
func (d *Server) Unmarshal(buf []byte) (uint64, error) {
|
||||
func (d *Network) Unmarshal(buf []byte) (uint64, error) {
|
||||
i := uint64(0)
|
||||
|
||||
{
|
||||
|
@ -762,7 +762,7 @@ func (d *Server) Unmarshal(buf []byte) (uint64, error) {
|
|||
func (d *Channel) Size() (s uint64) {
|
||||
|
||||
{
|
||||
l := uint64(len(d.Server))
|
||||
l := uint64(len(d.Network))
|
||||
|
||||
{
|
||||
|
||||
|
@ -805,7 +805,7 @@ func (d *Channel) Marshal(buf []byte) ([]byte, error) {
|
|||
i := uint64(0)
|
||||
|
||||
{
|
||||
l := uint64(len(d.Server))
|
||||
l := uint64(len(d.Network))
|
||||
|
||||
{
|
||||
|
||||
|
@ -820,7 +820,7 @@ func (d *Channel) Marshal(buf []byte) ([]byte, error) {
|
|||
i++
|
||||
|
||||
}
|
||||
copy(buf[i+0:], d.Server)
|
||||
copy(buf[i+0:], d.Network)
|
||||
i += l
|
||||
}
|
||||
{
|
||||
|
@ -865,7 +865,7 @@ func (d *Channel) Unmarshal(buf []byte) (uint64, error) {
|
|||
l = t
|
||||
|
||||
}
|
||||
d.Server = string(buf[i+0 : i+0+l])
|
||||
d.Network = string(buf[i+0 : i+0+l])
|
||||
i += l
|
||||
}
|
||||
{
|
||||
|
|
146
storage/user.go
146
storage/user.go
|
@ -6,6 +6,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/khlieng/dispatch/pkg/irc"
|
||||
"github.com/kjk/betterguid"
|
||||
)
|
||||
|
||||
|
@ -58,7 +59,7 @@ func NewUser(store Store) (*User, error) {
|
|||
}
|
||||
|
||||
func LoadUsers(store Store) ([]*User, error) {
|
||||
users, err := store.GetUsers()
|
||||
users, err := store.Users()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -76,15 +77,15 @@ func LoadUsers(store Store) ([]*User, error) {
|
|||
user.lastMessages = map[string]map[string]*Message{}
|
||||
user.loadCertificate()
|
||||
|
||||
channels, err := user.GetChannels()
|
||||
channels, err := user.Channels()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, channel := range channels {
|
||||
messages, _, err := user.GetLastMessages(channel.Server, channel.Name, 1)
|
||||
messages, _, err := user.LastMessages(channel.Network, channel.Name, 1)
|
||||
if err == nil && len(messages) == 1 {
|
||||
user.lastMessages[channel.Server] = map[string]*Message{
|
||||
user.lastMessages[channel.Network] = map[string]*Message{
|
||||
channel.Name: &messages[0],
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +132,7 @@ func DefaultClientSettings() *ClientSettings {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *User) GetClientSettings() *ClientSettings {
|
||||
func (u *User) ClientSettings() *ClientSettings {
|
||||
u.lock.Lock()
|
||||
settings := *u.clientSettings
|
||||
u.lock.Unlock()
|
||||
|
@ -158,91 +159,88 @@ func (u *User) UnmarshalClientSettingsJSON(b []byte) error {
|
|||
return u.store.SaveUser(u)
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
Name string
|
||||
Host string
|
||||
Port string
|
||||
TLS bool
|
||||
ServerPassword string
|
||||
Nick string
|
||||
Username string
|
||||
Realname string
|
||||
Account string
|
||||
Password string
|
||||
func (u *User) NewNetwork(template *Network, client *irc.Client) *Network {
|
||||
if template == nil {
|
||||
template = &Network{}
|
||||
}
|
||||
|
||||
template.user = u
|
||||
template.client = client
|
||||
template.channels = map[string]*Channel{}
|
||||
|
||||
return template
|
||||
}
|
||||
|
||||
func (u *User) GetServer(address string) (*Server, error) {
|
||||
return u.store.GetServer(u, address)
|
||||
func (u *User) Network(address string) (*Network, error) {
|
||||
return u.store.Network(u, address)
|
||||
}
|
||||
|
||||
func (u *User) GetServers() ([]*Server, error) {
|
||||
return u.store.GetServers(u)
|
||||
func (u *User) Networks() ([]*Network, error) {
|
||||
return u.store.Networks(u)
|
||||
}
|
||||
|
||||
func (u *User) AddServer(server *Server) error {
|
||||
return u.store.SaveServer(u, server)
|
||||
func (u *User) SaveNetwork(network *Network) error {
|
||||
return u.store.SaveNetwork(u, network)
|
||||
}
|
||||
|
||||
func (u *User) RemoveServer(address string) error {
|
||||
return u.store.RemoveServer(u, address)
|
||||
func (u *User) RemoveNetwork(address string) error {
|
||||
return u.store.RemoveNetwork(u, address)
|
||||
}
|
||||
|
||||
func (u *User) SetNick(nick, address string) error {
|
||||
server, err := u.GetServer(address)
|
||||
network, err := u.Network(address)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
server.Nick = nick
|
||||
return u.AddServer(server)
|
||||
network.Nick = nick
|
||||
return u.SaveNetwork(network)
|
||||
}
|
||||
|
||||
func (u *User) SetServerName(name, address string) error {
|
||||
server, err := u.GetServer(address)
|
||||
func (u *User) SetNetworkName(name, address string) error {
|
||||
network, err := u.Network(address)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
server.Name = name
|
||||
return u.AddServer(server)
|
||||
network.Name = name
|
||||
return u.SaveNetwork(network)
|
||||
}
|
||||
|
||||
type Channel struct {
|
||||
Server string
|
||||
Name string
|
||||
Topic string
|
||||
func (u *User) Channels() ([]*Channel, error) {
|
||||
return u.store.Channels(u)
|
||||
}
|
||||
|
||||
func (u *User) GetChannels() ([]*Channel, error) {
|
||||
return u.store.GetChannels(u)
|
||||
func (u *User) SaveChannel(channel *Channel) error {
|
||||
return u.store.SaveChannel(u, channel)
|
||||
}
|
||||
|
||||
func (u *User) AddChannel(channel *Channel) error {
|
||||
return u.store.AddChannel(u, channel)
|
||||
func (u *User) RemoveChannel(network, channel string) error {
|
||||
return u.store.RemoveChannel(u, network, channel)
|
||||
}
|
||||
|
||||
func (u *User) RemoveChannel(server, channel string) error {
|
||||
return u.store.RemoveChannel(u, server, channel)
|
||||
func (u *User) HasChannel(network, channel string) bool {
|
||||
return u.store.HasChannel(u, network, channel)
|
||||
}
|
||||
|
||||
type Tab struct {
|
||||
Server string
|
||||
Name string
|
||||
Network string
|
||||
Name string
|
||||
}
|
||||
|
||||
func (u *User) GetOpenDMs() ([]Tab, error) {
|
||||
return u.store.GetOpenDMs(u)
|
||||
func (u *User) OpenDMs() ([]Tab, error) {
|
||||
return u.store.OpenDMs(u)
|
||||
}
|
||||
|
||||
func (u *User) AddOpenDM(server, nick string) error {
|
||||
return u.store.AddOpenDM(u, server, nick)
|
||||
func (u *User) AddOpenDM(network, nick string) error {
|
||||
return u.store.AddOpenDM(u, network, nick)
|
||||
}
|
||||
|
||||
func (u *User) RemoveOpenDM(server, nick string) error {
|
||||
return u.store.RemoveOpenDM(u, server, nick)
|
||||
func (u *User) RemoveOpenDM(network, nick string) error {
|
||||
return u.store.RemoveOpenDM(u, network, nick)
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
ID string `json:"-" bleve:"-"`
|
||||
Server string `json:"-" bleve:"server"`
|
||||
Network string `json:"-" bleve:"server"`
|
||||
From string `bleve:"-"`
|
||||
To string `json:"-" bleve:"to"`
|
||||
Content string `bleve:"content"`
|
||||
|
@ -267,7 +265,7 @@ func (u *User) LogMessage(msg *Message) error {
|
|||
msg.To = msg.From
|
||||
}
|
||||
|
||||
u.setLastMessage(msg.Server, msg.To, msg)
|
||||
u.setLastMessage(msg.Network, msg.To, msg)
|
||||
|
||||
err := u.messageLog.LogMessage(msg)
|
||||
if err != nil {
|
||||
|
@ -282,7 +280,7 @@ type Event struct {
|
|||
Time int64
|
||||
}
|
||||
|
||||
func (u *User) LogEvent(server, name string, params []string, channels ...string) error {
|
||||
func (u *User) LogEvent(network, name string, params []string, channels ...string) error {
|
||||
now := time.Now().Unix()
|
||||
event := Event{
|
||||
Type: name,
|
||||
|
@ -291,11 +289,11 @@ func (u *User) LogEvent(server, name string, params []string, channels ...string
|
|||
}
|
||||
|
||||
for _, channel := range channels {
|
||||
lastMessage := u.getLastMessage(server, channel)
|
||||
lastMessage := u.getLastMessage(network, channel)
|
||||
|
||||
if lastMessage != nil && shouldCollapse(lastMessage, event) {
|
||||
lastMessage.Events = append(lastMessage.Events, event)
|
||||
u.setLastMessage(server, channel, lastMessage)
|
||||
u.setLastMessage(network, channel, lastMessage)
|
||||
|
||||
err := u.messageLog.LogMessage(lastMessage)
|
||||
if err != nil {
|
||||
|
@ -303,13 +301,13 @@ func (u *User) LogEvent(server, name string, params []string, channels ...string
|
|||
}
|
||||
} else {
|
||||
msg := &Message{
|
||||
ID: betterguid.New(),
|
||||
Server: server,
|
||||
To: channel,
|
||||
Time: now,
|
||||
Events: []Event{event},
|
||||
ID: betterguid.New(),
|
||||
Network: network,
|
||||
To: channel,
|
||||
Time: now,
|
||||
Events: []Event{event},
|
||||
}
|
||||
u.setLastMessage(server, channel, msg)
|
||||
u.setLastMessage(network, channel, msg)
|
||||
|
||||
err := u.messageLog.LogMessage(msg)
|
||||
if err != nil {
|
||||
|
@ -338,15 +336,15 @@ func shouldCollapse(msg *Message, event Event) bool {
|
|||
return matches == 2
|
||||
}
|
||||
|
||||
func (u *User) getLastMessage(server, channel string) *Message {
|
||||
func (u *User) getLastMessage(network, channel string) *Message {
|
||||
u.lock.Lock()
|
||||
defer u.lock.Unlock()
|
||||
|
||||
if _, ok := u.lastMessages[server]; !ok {
|
||||
if _, ok := u.lastMessages[network]; !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
last := u.lastMessages[server][channel]
|
||||
last := u.lastMessages[network][channel]
|
||||
if last != nil {
|
||||
msg := *last
|
||||
return &msg
|
||||
|
@ -354,30 +352,30 @@ func (u *User) getLastMessage(server, channel string) *Message {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u *User) setLastMessage(server, channel string, msg *Message) {
|
||||
func (u *User) setLastMessage(network, channel string, msg *Message) {
|
||||
u.lock.Lock()
|
||||
|
||||
if _, ok := u.lastMessages[server]; !ok {
|
||||
u.lastMessages[server] = map[string]*Message{}
|
||||
if _, ok := u.lastMessages[network]; !ok {
|
||||
u.lastMessages[network] = map[string]*Message{}
|
||||
}
|
||||
|
||||
u.lastMessages[server][channel] = msg
|
||||
u.lastMessages[network][channel] = msg
|
||||
u.lock.Unlock()
|
||||
}
|
||||
|
||||
func (u *User) GetMessages(server, channel string, count int, fromID string) ([]Message, bool, error) {
|
||||
return u.messageLog.GetMessages(server, channel, count, fromID)
|
||||
func (u *User) Messages(network, channel string, count int, fromID string) ([]Message, bool, error) {
|
||||
return u.messageLog.Messages(network, channel, count, fromID)
|
||||
}
|
||||
|
||||
func (u *User) GetLastMessages(server, channel string, count int) ([]Message, bool, error) {
|
||||
return u.GetMessages(server, channel, count, "")
|
||||
func (u *User) LastMessages(network, channel string, count int) ([]Message, bool, error) {
|
||||
return u.Messages(network, channel, count, "")
|
||||
}
|
||||
|
||||
func (u *User) SearchMessages(server, channel, q string) ([]Message, error) {
|
||||
ids, err := u.messageIndex.SearchMessages(server, channel, q)
|
||||
func (u *User) SearchMessages(network, channel, q string) ([]Message, error) {
|
||||
ids, err := u.messageIndex.SearchMessages(network, channel, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u.messageLog.GetMessagesByID(server, channel, ids)
|
||||
return u.messageLog.MessagesByID(network, channel, ids)
|
||||
}
|
||||
|
|
|
@ -34,23 +34,23 @@ func TestUser(t *testing.T) {
|
|||
user, err := storage.NewUser(db)
|
||||
assert.Nil(t, err)
|
||||
|
||||
srv := &storage.Server{
|
||||
srv := &storage.Network{
|
||||
Name: "freenode",
|
||||
Host: "irc.freenode.net",
|
||||
Nick: "test",
|
||||
}
|
||||
chan1 := &storage.Channel{
|
||||
Server: srv.Host,
|
||||
Name: "#test",
|
||||
Network: srv.Host,
|
||||
Name: "#test",
|
||||
}
|
||||
chan2 := &storage.Channel{
|
||||
Server: srv.Host,
|
||||
Name: "#testing",
|
||||
Network: srv.Host,
|
||||
Name: "#testing",
|
||||
}
|
||||
|
||||
user.AddServer(srv)
|
||||
user.AddChannel(chan1)
|
||||
user.AddChannel(chan2)
|
||||
user.SaveNetwork(srv)
|
||||
user.SaveChannel(chan1)
|
||||
user.SaveChannel(chan2)
|
||||
|
||||
users, err := storage.LoadUsers(db)
|
||||
assert.Nil(t, err)
|
||||
|
@ -59,52 +59,52 @@ func TestUser(t *testing.T) {
|
|||
user = users[0]
|
||||
assert.Equal(t, uint64(1), user.ID)
|
||||
|
||||
servers, err := user.GetServers()
|
||||
servers, err := user.Networks()
|
||||
assert.Len(t, servers, 1)
|
||||
assert.Equal(t, srv, servers[0])
|
||||
|
||||
channels, err := user.GetChannels()
|
||||
channels, err := user.Channels()
|
||||
assert.Len(t, channels, 2)
|
||||
assert.Equal(t, chan1, channels[0])
|
||||
assert.Equal(t, chan2, channels[1])
|
||||
|
||||
user.SetNick("bob", srv.Host)
|
||||
servers, err = user.GetServers()
|
||||
servers, err = user.Networks()
|
||||
assert.Equal(t, "bob", servers[0].Nick)
|
||||
|
||||
user.SetServerName("cake", srv.Host)
|
||||
servers, err = user.GetServers()
|
||||
user.SetNetworkName("cake", srv.Host)
|
||||
servers, err = user.Networks()
|
||||
assert.Equal(t, "cake", servers[0].Name)
|
||||
|
||||
user.RemoveChannel(srv.Host, chan1.Name)
|
||||
channels, err = user.GetChannels()
|
||||
channels, err = user.Channels()
|
||||
assert.Len(t, channels, 1)
|
||||
assert.Equal(t, chan2, channels[0])
|
||||
|
||||
user.RemoveServer(srv.Host)
|
||||
servers, err = user.GetServers()
|
||||
user.RemoveNetwork(srv.Host)
|
||||
servers, err = user.Networks()
|
||||
assert.Len(t, servers, 0)
|
||||
channels, err = user.GetChannels()
|
||||
channels, err = user.Channels()
|
||||
assert.Len(t, channels, 0)
|
||||
|
||||
user.AddOpenDM(srv.Host, "cake")
|
||||
openDMs, err := user.GetOpenDMs()
|
||||
openDMs, err := user.OpenDMs()
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, openDMs, 1)
|
||||
err = user.RemoveOpenDM(srv.Host, "cake")
|
||||
assert.Nil(t, err)
|
||||
openDMs, err = user.GetOpenDMs()
|
||||
openDMs, err = user.OpenDMs()
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, openDMs, 0)
|
||||
|
||||
settings := user.GetClientSettings()
|
||||
settings := user.ClientSettings()
|
||||
assert.NotNil(t, settings)
|
||||
assert.Equal(t, storage.DefaultClientSettings(), settings)
|
||||
|
||||
settings.ColoredNicks = !settings.ColoredNicks
|
||||
err = user.SetClientSettings(settings)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, settings, user.GetClientSettings())
|
||||
assert.Equal(t, settings, user.ClientSettings())
|
||||
assert.NotEqual(t, settings, storage.DefaultClientSettings())
|
||||
|
||||
user.AddOpenDM(srv.Host, "cake")
|
||||
|
@ -113,7 +113,7 @@ func TestUser(t *testing.T) {
|
|||
_, err = os.Stat(storage.Path.User(user.Username))
|
||||
assert.True(t, os.IsNotExist(err))
|
||||
|
||||
openDMs, err = user.GetOpenDMs()
|
||||
openDMs, err = user.OpenDMs()
|
||||
assert.Nil(t, err)
|
||||
assert.Len(t, openDMs, 0)
|
||||
|
||||
|
@ -143,12 +143,12 @@ func TestMessages(t *testing.T) {
|
|||
|
||||
os.MkdirAll(storage.Path.User(user.Username), 0700)
|
||||
|
||||
messages, hasMore, err := user.GetMessages("irc.freenode.net", "#go-nuts", 10, "6")
|
||||
messages, hasMore, err := user.Messages("irc.freenode.net", "#go-nuts", 10, "6")
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, hasMore)
|
||||
assert.Len(t, messages, 0)
|
||||
|
||||
messages, hasMore, err = user.GetLastMessages("irc.freenode.net", "#go-nuts", 10)
|
||||
messages, hasMore, err = user.LastMessages("irc.freenode.net", "#go-nuts", 10)
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, hasMore)
|
||||
assert.Len(t, messages, 0)
|
||||
|
@ -163,7 +163,7 @@ func TestMessages(t *testing.T) {
|
|||
ids = append(ids, id)
|
||||
err = user.LogMessage(&storage.Message{
|
||||
ID: id,
|
||||
Server: "irc.freenode.net",
|
||||
Network: "irc.freenode.net",
|
||||
From: "nick",
|
||||
To: "#go-nuts",
|
||||
Content: "message" + strconv.Itoa(i),
|
||||
|
@ -171,35 +171,35 @@ func TestMessages(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
messages, hasMore, err = user.GetMessages("irc.freenode.net", "#go-nuts", 10, ids[4])
|
||||
messages, hasMore, err = user.Messages("irc.freenode.net", "#go-nuts", 10, ids[4])
|
||||
assert.Equal(t, "message0", messages[0].Content)
|
||||
assert.Equal(t, "message3", messages[3].Content)
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, hasMore)
|
||||
assert.Len(t, messages, 4)
|
||||
|
||||
messages, hasMore, err = user.GetMessages("irc.freenode.net", "#go-nuts", 10, betterguid.New())
|
||||
messages, hasMore, err = user.Messages("irc.freenode.net", "#go-nuts", 10, betterguid.New())
|
||||
assert.Equal(t, "message0", messages[0].Content)
|
||||
assert.Equal(t, "message4", messages[4].Content)
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, hasMore)
|
||||
assert.Len(t, messages, 5)
|
||||
|
||||
messages, hasMore, err = user.GetMessages("irc.freenode.net", "#go-nuts", 10, ids[2])
|
||||
messages, hasMore, err = user.Messages("irc.freenode.net", "#go-nuts", 10, ids[2])
|
||||
assert.Equal(t, "message0", messages[0].Content)
|
||||
assert.Equal(t, "message1", messages[1].Content)
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, hasMore)
|
||||
assert.Len(t, messages, 2)
|
||||
|
||||
messages, hasMore, err = user.GetLastMessages("irc.freenode.net", "#go-nuts", 10)
|
||||
messages, hasMore, err = user.LastMessages("irc.freenode.net", "#go-nuts", 10)
|
||||
assert.Equal(t, "message0", messages[0].Content)
|
||||
assert.Equal(t, "message4", messages[4].Content)
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, hasMore)
|
||||
assert.Len(t, messages, 5)
|
||||
|
||||
messages, hasMore, err = user.GetLastMessages("irc.freenode.net", "#go-nuts", 4)
|
||||
messages, hasMore, err = user.LastMessages("irc.freenode.net", "#go-nuts", 4)
|
||||
assert.Equal(t, "message1", messages[0].Content)
|
||||
assert.Equal(t, "message4", messages[3].Content)
|
||||
assert.Nil(t, err)
|
||||
|
@ -211,7 +211,7 @@ func TestMessages(t *testing.T) {
|
|||
assert.True(t, len(messages) > 0)
|
||||
|
||||
user.LogEvent("irc.freenode.net", "join", []string{"bob"}, "#go-nuts")
|
||||
messages, hasMore, err = user.GetLastMessages("irc.freenode.net", "#go-nuts", 1)
|
||||
messages, hasMore, err = user.LastMessages("irc.freenode.net", "#go-nuts", 1)
|
||||
assert.Zero(t, messages[0].Content)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, hasMore)
|
||||
|
@ -220,7 +220,7 @@ func TestMessages(t *testing.T) {
|
|||
assert.NotZero(t, messages[0].Events[0].Time)
|
||||
|
||||
user.LogEvent("irc.freenode.net", "part", []string{"bob"}, "#go-nuts")
|
||||
messages, hasMore, err = user.GetLastMessages("irc.freenode.net", "#go-nuts", 1)
|
||||
messages, hasMore, err = user.LastMessages("irc.freenode.net", "#go-nuts", 1)
|
||||
assert.Zero(t, messages[0].Content)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, hasMore)
|
||||
|
@ -229,7 +229,7 @@ func TestMessages(t *testing.T) {
|
|||
assert.NotZero(t, messages[0].Events[0].Time)
|
||||
|
||||
user.LogEvent("irc.freenode.net", "nick", []string{"bob", "rob"}, "#go-nuts")
|
||||
messages, hasMore, err = user.GetLastMessages("irc.freenode.net", "#go-nuts", 1)
|
||||
messages, hasMore, err = user.LastMessages("irc.freenode.net", "#go-nuts", 1)
|
||||
assert.Zero(t, messages[0].Content)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, hasMore)
|
||||
|
@ -238,7 +238,7 @@ func TestMessages(t *testing.T) {
|
|||
assert.NotZero(t, messages[0].Events[0].Time)
|
||||
|
||||
user.LogEvent("irc.freenode.net", "quit", []string{"rob", "bored"}, "#go-nuts")
|
||||
messages, hasMore, err = user.GetLastMessages("irc.freenode.net", "#go-nuts", 1)
|
||||
messages, hasMore, err = user.LastMessages("irc.freenode.net", "#go-nuts", 1)
|
||||
assert.Zero(t, messages[0].Content)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, hasMore)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue