-
Notifications
You must be signed in to change notification settings - Fork 35
/
user.go
153 lines (127 loc) · 2.86 KB
/
user.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package hal
import (
"encoding/json"
"fmt"
"sync"
)
// User is a chat participant
type User struct {
ID string
Name string
Roles []string
Options map[string]interface{}
}
func (u *User) Get(k string) (interface{}, error) {
v, ok := u.Options[k]
if !ok {
return nil, fmt.Errorf("%s not found in user options", k)
}
return v, nil
}
func NewUser() *User {
return &User{
Options: make(map[string]interface{}),
}
}
// UserMap handles the known users
type UserMap struct {
Map map[string]User
robot *Robot
sync.Mutex
}
// NewUserMap returns an initialized UserMap
func NewUserMap(robot *Robot) *UserMap {
return &UserMap{
Map: make(map[string]User, 0),
robot: robot,
}
}
// All returns the underlying map of all users
func (um *UserMap) All() []User {
um.Lock()
users := make([]User, len(um.Map))
for _, user := range um.Map {
users = append(users, user)
}
um.Unlock()
return users
}
// Get looks up a user by id and returns a User object
func (um *UserMap) Get(id string) (User, error) {
um.Lock()
defer um.Unlock()
user, ok := um.Map[id]
if !ok {
return User{}, fmt.Errorf("could not find user with id %s", id)
}
return user, nil
}
// GetByName looks up a user by name and returns a User object
func (um *UserMap) GetByName(name string) (User, error) {
um.Lock()
defer um.Unlock()
for _, user := range um.Map {
if user.Name == name {
if user.Options == nil {
user.Options = make(map[string]interface{})
}
return user, nil
}
}
return User{Options: make(map[string]interface{})}, fmt.Errorf("could not find user with name %s", name)
}
// Set adds or updates a user in the UserMap and persists it to the store
func (um *UserMap) Set(id string, user User) error {
um.Lock()
// initialize user.Options if nothing's in there yet
if user.Options == nil {
user.Options = make(map[string]interface{})
}
um.Map[id] = user
if err := um.Save(); err != nil {
um.Unlock()
return err
}
um.Unlock()
return nil
}
// Encode marshals a UserMap to JSON
func (um *UserMap) Encode() ([]byte, error) {
data, err := json.Marshal(um.Map)
if err != nil {
return []byte{}, err
}
return data, err
}
// Decode unmarshals a JSON object into a map of strings to Users
func (um *UserMap) Decode() (map[string]User, error) {
data, err := um.robot.Store.Get("users")
if err != nil {
return nil, err
}
users := map[string]User{}
if err := json.Unmarshal(data, &users); err != nil {
return users, err
}
return users, nil
}
// Load retrieves known users from the store and populates the UserMap
func (um *UserMap) Load() error {
um.Lock()
data, err := um.Decode()
if err != nil {
um.Unlock()
return err
}
um.Map = data
um.Unlock()
return nil
}
// Save persists known users to the store
func (um *UserMap) Save() error {
data, err := um.Encode()
if err != nil {
return err
}
return um.robot.Store.Set("users", data)
}