-
Notifications
You must be signed in to change notification settings - Fork 0
/
stored_user_state.go
133 lines (113 loc) · 3.08 KB
/
stored_user_state.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
package main
import (
"encoding/json"
"errors"
"log"
"sort"
"strconv"
"time"
"github.com/boltdb/bolt"
)
// UserState stores the state of user's registration
// 0 (nothing)
// 1 (user asked about bus number)
// 2 (user asked about bus stop number)
// 3 (user asked about which days, can self loop)
// 4 (user asked about what time)
// 5 (user asked which alarm to delete)
type UserState struct {
State int
BusInfoJob
SelectedDays map[time.Weekday]bool
}
// ToggleDay toggles the truthy selection of the day
func (userState *UserState) ToggleDay(day time.Weekday) {
userState.SelectedDays[day] = !userState.SelectedDays[day]
}
// GetSelectedDays gets a list of selected days
func (userState *UserState) GetSelectedDays() []time.Weekday {
selectedDays := []time.Weekday{}
for k, v := range userState.SelectedDays {
if v {
selectedDays = append(selectedDays, k)
}
}
sort.Slice(selectedDays, func(i, j int) bool {
return int(selectedDays[i]) < int(selectedDays[j])
})
return selectedDays
}
// UserStateDB contains the operations to store/retrieve/delete user states,
// holding information about the stage of registration that the user is at
type UserStateDB struct {
dbFile string
statesBucket string
}
// NewUserStateDB returns an initialised instance of UserStateDB
func NewUserStateDB(dbFile string) UserStateDB {
return UserStateDB{dbFile: dbFile, statesBucket: "users"}
}
// GetUserState retrieves the stored user state
func (s *UserStateDB) GetUserState(chatID int64) *UserState {
key := []byte(strconv.FormatInt(chatID, 10))
var storedUserState UserState
db, err := bolt.Open(s.dbFile, 0600, nil)
if err != nil {
log.Fatalln(err)
}
defer db.Close()
err = db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(s.statesBucket))
if b == nil {
return errors.New("Bucket does not exist")
}
storedValue := b.Get(key)
if storedValue == nil {
return errors.New("Key does not exist")
}
json.Unmarshal(storedValue, &storedUserState)
return nil
})
// If there's no matching record in database
if err != nil {
return nil
}
return &storedUserState
}
// SaveUserState saves the user state,
func (s *UserStateDB) SaveUserState(chatID int64, userState UserState) {
userState.ChatID = chatID
log.Println("Saving user interaction state:", userState)
key := []byte(strconv.FormatInt(chatID, 10))
db, err := bolt.Open(s.dbFile, 0600, nil)
if err != nil {
log.Fatalln(err)
}
defer db.Close()
db.Update(func(tx *bolt.Tx) error {
b, err := tx.CreateBucketIfNotExists([]byte(s.statesBucket))
if err != nil {
log.Fatalln(err)
}
encUserState, err := json.Marshal(userState)
b.Put(key, encUserState)
return nil
})
}
// DeleteUserState deletes the saved user state
func (s *UserStateDB) DeleteUserState(chatID int64) {
key := []byte(strconv.FormatInt(chatID, 10))
db, err := bolt.Open(s.dbFile, 0600, nil)
if err != nil {
log.Fatalln(err)
}
defer db.Close()
db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(s.statesBucket))
if b == nil {
log.Fatalln("Bucket should exist but doesn't exist")
}
b.Delete(key)
return nil
})
}