dispatch/storage/user.go

383 lines
7.5 KiB
Go
Raw Normal View History

2015-01-17 01:37:21 +00:00
package storage
import (
2016-01-22 17:30:47 +00:00
"crypto/tls"
"os"
2016-01-22 17:30:47 +00:00
"sync"
"time"
2020-06-15 08:58:51 +00:00
"github.com/khlieng/dispatch/pkg/irc"
"github.com/kjk/betterguid"
2015-01-17 01:37:21 +00:00
)
2016-01-22 17:30:47 +00:00
type User struct {
ID uint64
IDBytes []byte
2016-01-22 17:30:47 +00:00
Username string
2018-10-15 06:56:17 +00:00
store Store
messageLog MessageStore
messageIndex MessageSearchProvider
lastMessages map[string]map[string]*Message
2018-10-15 06:56:17 +00:00
clientSettings *ClientSettings
lastIP []byte
certificate *tls.Certificate
lock sync.Mutex
2016-01-22 17:30:47 +00:00
}
func NewUser(store Store) (*User, error) {
2018-10-15 06:56:17 +00:00
user := &User{
store: store,
clientSettings: DefaultClientSettings(),
lastMessages: map[string]map[string]*Message{},
2018-10-15 06:56:17 +00:00
}
2015-01-17 01:37:21 +00:00
err := store.SaveUser(user)
if err != nil {
2016-01-17 20:15:29 +00:00
return nil, err
}
2015-01-17 01:37:21 +00:00
2020-06-04 00:28:41 +00:00
err = os.MkdirAll(Path.User(user.Username), 0700)
if err != nil {
return nil, err
}
2020-06-04 00:28:41 +00:00
err = os.Mkdir(Path.Downloads(user.Username), 0700)
if err != nil {
2016-01-17 20:15:29 +00:00
return nil, err
}
2020-06-04 00:28:41 +00:00
user.messageLog, err = GetMessageStore(user)
if err != nil {
return nil, err
}
2020-06-04 00:28:41 +00:00
user.messageIndex, err = GetMessageSearchProvider(user)
2020-05-17 00:31:50 +00:00
if err != nil {
return nil, err
}
2016-01-17 20:15:29 +00:00
return user, nil
2015-01-17 01:37:21 +00:00
}
func LoadUsers(store Store) ([]*User, error) {
2020-06-15 08:58:51 +00:00
users, err := store.Users()
if err != nil {
return nil, err
}
2015-01-17 01:37:21 +00:00
for _, user := range users {
user.store = store
user.messageLog, err = GetMessageStore(user)
if err != nil {
return nil, err
}
user.messageIndex, err = GetMessageSearchProvider(user)
if err != nil {
return nil, err
}
user.lastMessages = map[string]map[string]*Message{}
user.loadCertificate()
2020-06-15 08:58:51 +00:00
channels, err := user.Channels()
if err != nil {
return nil, err
}
for _, channel := range channels {
2020-06-15 08:58:51 +00:00
messages, _, err := user.LastMessages(channel.Network, channel.Name, 1)
if err == nil && len(messages) == 1 {
2020-06-15 08:58:51 +00:00
user.lastMessages[channel.Network] = map[string]*Message{
channel.Name: &messages[0],
}
}
}
}
return users, nil
2015-01-17 01:37:21 +00:00
}
func (u *User) Remove() {
u.store.DeleteUser(u)
if u.messageLog != nil {
u.messageLog.Close()
}
if u.messageIndex != nil {
u.messageIndex.Close()
}
2020-04-20 01:02:15 +00:00
os.RemoveAll(Path.User(u.Username))
2015-01-17 01:37:21 +00:00
}
func (u *User) GetLastIP() []byte {
u.lock.Lock()
ip := u.lastIP
u.lock.Unlock()
return ip
}
func (u *User) SetLastIP(ip []byte) error {
u.lock.Lock()
u.lastIP = ip
u.lock.Unlock()
return u.store.SaveUser(u)
}
2018-10-15 06:56:17 +00:00
//easyjson:json
type ClientSettings struct {
ColoredNicks bool
}
func DefaultClientSettings() *ClientSettings {
return &ClientSettings{
ColoredNicks: true,
}
}
2020-06-15 08:58:51 +00:00
func (u *User) ClientSettings() *ClientSettings {
2018-10-15 06:56:17 +00:00
u.lock.Lock()
settings := *u.clientSettings
u.lock.Unlock()
return &settings
}
func (u *User) SetClientSettings(settings *ClientSettings) error {
u.lock.Lock()
u.clientSettings = settings
u.lock.Unlock()
return u.store.SaveUser(u)
}
func (u *User) UnmarshalClientSettingsJSON(b []byte) error {
u.lock.Lock()
err := u.clientSettings.UnmarshalJSON(b)
u.lock.Unlock()
if err != nil {
return err
}
return u.store.SaveUser(u)
}
2020-06-15 08:58:51 +00:00
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{}
2020-06-15 23:29:35 +00:00
template.lock = &sync.Mutex{}
2020-06-15 08:58:51 +00:00
return template
2015-01-17 01:37:21 +00:00
}
2020-06-15 08:58:51 +00:00
func (u *User) Network(address string) (*Network, error) {
return u.store.Network(u, address)
2019-01-27 07:53:07 +00:00
}
2020-06-15 08:58:51 +00:00
func (u *User) Networks() ([]*Network, error) {
return u.store.Networks(u)
}
2015-02-04 01:43:49 +00:00
2020-06-15 08:58:51 +00:00
func (u *User) SaveNetwork(network *Network) error {
return u.store.SaveNetwork(u, network)
2015-02-04 01:43:49 +00:00
}
2020-06-15 08:58:51 +00:00
func (u *User) RemoveNetwork(address string) error {
return u.store.RemoveNetwork(u, address)
}
func (u *User) SetNick(nick, address string) error {
2020-06-15 08:58:51 +00:00
network, err := u.Network(address)
2019-01-27 07:53:07 +00:00
if err != nil {
return err
}
2020-06-15 08:58:51 +00:00
network.Nick = nick
return u.SaveNetwork(network)
}
2020-06-15 08:58:51 +00:00
func (u *User) SetNetworkName(name, address string) error {
network, err := u.Network(address)
2019-01-27 07:53:07 +00:00
if err != nil {
return err
}
2020-06-15 08:58:51 +00:00
network.Name = name
return u.SaveNetwork(network)
}
2020-06-15 08:58:51 +00:00
func (u *User) Channels() ([]*Channel, error) {
return u.store.Channels(u)
}
2020-06-15 08:58:51 +00:00
func (u *User) SaveChannel(channel *Channel) error {
return u.store.SaveChannel(u, channel)
}
2020-06-15 08:58:51 +00:00
func (u *User) RemoveChannel(network, channel string) error {
return u.store.RemoveChannel(u, network, channel)
}
2020-06-15 08:58:51 +00:00
func (u *User) HasChannel(network, channel string) bool {
return u.store.HasChannel(u, network, channel)
}
2015-01-17 01:37:21 +00:00
type Tab struct {
2020-06-15 08:58:51 +00:00
Network string
Name string
}
2020-06-15 08:58:51 +00:00
func (u *User) OpenDMs() ([]Tab, error) {
return u.store.OpenDMs(u)
}
2020-06-15 08:58:51 +00:00
func (u *User) AddOpenDM(network, nick string) error {
return u.store.AddOpenDM(u, network, nick)
}
2020-06-15 08:58:51 +00:00
func (u *User) RemoveOpenDM(network, nick string) error {
return u.store.RemoveOpenDM(u, network, nick)
}
type Message struct {
ID string `json:"-" bleve:"-"`
2020-06-15 08:58:51 +00:00
Network string `json:"-" bleve:"server"`
From string `bleve:"-"`
To string `json:"-" bleve:"to"`
Content string `bleve:"content"`
Time int64 `bleve:"-"`
Events []Event `bleve:"-"`
2015-01-17 01:37:21 +00:00
}
func (m Message) Type() string {
return "message"
}
2015-01-17 01:37:21 +00:00
func (u *User) LogMessage(msg *Message) error {
if msg.Time == 0 {
msg.Time = time.Now().Unix()
}
if msg.ID == "" {
msg.ID = betterguid.New()
}
if msg.To == "" {
msg.To = msg.From
}
2020-06-15 08:58:51 +00:00
u.setLastMessage(msg.Network, msg.To, msg)
err := u.messageLog.LogMessage(msg)
if err != nil {
return err
}
return u.messageIndex.Index(msg.ID, msg)
}
type Event struct {
Type string
Params []string
Time int64
}
2020-06-15 08:58:51 +00:00
func (u *User) LogEvent(network, name string, params []string, channels ...string) error {
now := time.Now().Unix()
event := Event{
Type: name,
Params: params,
Time: now,
}
for _, channel := range channels {
2020-06-15 08:58:51 +00:00
lastMessage := u.getLastMessage(network, channel)
if lastMessage != nil && shouldCollapse(lastMessage, event) {
lastMessage.Events = append(lastMessage.Events, event)
2020-06-15 08:58:51 +00:00
u.setLastMessage(network, channel, lastMessage)
err := u.messageLog.LogMessage(lastMessage)
if err != nil {
return err
}
} else {
msg := &Message{
2020-06-15 08:58:51 +00:00
ID: betterguid.New(),
Network: network,
To: channel,
Time: now,
Events: []Event{event},
}
2020-06-15 08:58:51 +00:00
u.setLastMessage(network, channel, msg)
err := u.messageLog.LogMessage(msg)
if err != nil {
return err
}
}
}
return nil
}
var collapsed = []string{"join", "part", "quit"}
func shouldCollapse(msg *Message, event Event) bool {
matches := 0
if len(msg.Events) > 0 {
for _, collapseType := range collapsed {
if msg.Events[0].Type == collapseType {
matches++
}
if event.Type == collapseType {
matches++
}
}
}
return matches == 2
}
2020-06-15 08:58:51 +00:00
func (u *User) getLastMessage(network, channel string) *Message {
u.lock.Lock()
defer u.lock.Unlock()
2020-06-15 08:58:51 +00:00
if _, ok := u.lastMessages[network]; !ok {
return nil
}
2020-06-15 08:58:51 +00:00
last := u.lastMessages[network][channel]
if last != nil {
msg := *last
return &msg
}
return nil
}
2020-06-15 08:58:51 +00:00
func (u *User) setLastMessage(network, channel string, msg *Message) {
u.lock.Lock()
2020-06-15 08:58:51 +00:00
if _, ok := u.lastMessages[network]; !ok {
u.lastMessages[network] = map[string]*Message{}
}
2020-06-15 08:58:51 +00:00
u.lastMessages[network][channel] = msg
u.lock.Unlock()
}
2020-06-15 08:58:51 +00:00
func (u *User) Messages(network, channel string, count int, fromID string) ([]Message, bool, error) {
return u.messageLog.Messages(network, channel, count, fromID)
}
2020-06-15 08:58:51 +00:00
func (u *User) LastMessages(network, channel string, count int) ([]Message, bool, error) {
return u.Messages(network, channel, count, "")
}
2020-06-15 08:58:51 +00:00
func (u *User) SearchMessages(network, channel, q string) ([]Message, error) {
ids, err := u.messageIndex.SearchMessages(network, channel, q)
if err != nil {
return nil, err
}
2020-06-15 08:58:51 +00:00
return u.messageLog.MessagesByID(network, channel, ids)
}