-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
234 lines (223 loc) · 6.02 KB
/
main.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
package main
import (
"errors"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
telegram "github.com/go-telegram-bot-api/telegram-bot-api"
)
type woffu struct {
User string
Pass string
Corp string
BotToken string
ChatID int64
CheckInHour int
CheckInMinute int
CheckOutHour int
CheckOutMinute int
SeconsOfInprecission int
WorkingEventIDs []int
Bot *telegram.BotAPI
WoffuToken string
WoffuUID string
SkipList []string
}
func main() {
// Load config
w, err := newBot()
if err != nil {
panic(err)
}
// Get credentials
err = w.login()
if err != nil {
w.sendError(errors.New("Error login: " + err.Error() + ". This will cause panic!"))
panic(err)
}
// Endless loop, because work does never end
errCount := 0
for {
// Do nothing until check in/out time
isCheckIn, inprecission := w.sleepTillNext()
// Get events
evs, err := w.getEvents()
if err != nil {
// Maybe token has expired, renew credentials and retry
if errCount == 1 {
w.sendError(errors.New(err.Error() + ". This will cause panic!"))
panic("Too many consecutive errors")
} else {
w.sendError(err)
}
err = w.login()
if err != nil {
w.sendError(err)
}
errCount++
time.Sleep(10 * time.Second)
continue
}
// Check in/out if it's a working day
isWorkingDay := false
for _, id := range w.WorkingEventIDs {
if evs[0].ID == id {
isWorkingDay = true
break
}
}
isSkipDay := false
today := getCurrentDate()
for i, skipDate := range w.SkipList {
if skipDate == today {
isSkipDay = true
w.SkipList[i] = w.SkipList[len(w.SkipList)-1]
w.SkipList = w.SkipList[:len(w.SkipList)-1]
}
}
if isWorkingDay && !isSkipDay {
// It's a working day
if err := w.check(); err != nil {
w.sendError(err)
} else {
errCount = 0
if isCheckIn {
w.sendMessage("Checked in successfully")
} else {
w.sendMessage("Checked out successfully")
}
}
} else {
// It's NOT a working day
if isCheckIn {
if isSkipDay {
w.sendMessage("You told me to not check in today, so I won't")
} else {
w.sendMessage("Enjoy your free day 😎")
}
}
errCount = 0
fmt.Println("Free day, not checking in/out")
}
if inprecission < 0 {
time.Sleep(inprecission * -1)
}
time.Sleep(time.Minute)
}
}
func newBot() (*woffu, error) {
// Load config
w, err := loadConfig()
if err != nil {
return nil, err
}
// Run bot
err = w.runTelegramBot()
return w, err
}
func loadConfig() (*woffu, error) {
user := os.Getenv("WOFFU_USER")
if user == "" {
return nil, errors.New("WOFFU_USER env value is mandatory")
}
pass := os.Getenv("WOFFU_PASS")
if pass == "" {
return nil, errors.New("WOFFU_PASS env value is mandatory")
}
corp := os.Getenv("CORP")
if corp == "" {
return nil, errors.New("CORP env value is mandatory")
}
botToken := os.Getenv("BOT")
chatID, err := strconv.Atoi(os.Getenv("CHAT"))
if botToken != "" && err != nil {
return nil, err
}
parseTime := func(s string) (int, int, error) {
splitted := strings.Split(s, ":")
hour, err := strconv.Atoi(splitted[0])
if err != nil {
return 0, 0, err
}
minute, err := strconv.Atoi(splitted[1])
if err != nil {
return 0, 0, err
}
if hour < 0 || hour > 59 || minute < 0 || minute > 59 {
return 0, 0, errors.New("Wrong value")
}
return hour, minute, nil
}
checkInHour, checkInMinute, err := parseTime(os.Getenv("CHECKIN"))
if err != nil {
return nil, errors.New("Error parsing CHECKIN: " + err.Error())
}
checkOutHour, checkOutMinute, err := parseTime(os.Getenv("CHECKOUT"))
if err != nil {
return nil, errors.New("Error parsing CHECKOUT: " + err.Error())
}
splitted := strings.Split(os.Getenv("WORKINGDAYIDS"), ",")
workingIDs := []int{}
for _, idStr := range splitted {
id, err := strconv.Atoi(idStr)
if err != nil {
return nil, err
}
workingIDs = append(workingIDs, id)
}
secs, err := strconv.Atoi(os.Getenv("IMPRECISSION"))
if err != nil {
secs = 0
}
return &woffu{
User: user,
Pass: pass,
Corp: corp,
BotToken: botToken,
ChatID: int64(chatID),
CheckInHour: checkInHour,
CheckInMinute: checkInMinute,
CheckOutHour: checkOutHour,
CheckOutMinute: checkOutMinute,
SeconsOfInprecission: secs,
WorkingEventIDs: workingIDs,
SkipList: []string{},
}, nil
}
// sleepTillNext returns true if it has sleep until check in time, false for check out
func (w *woffu) sleepTillNext() (bool, time.Duration) {
currentTime := time.Now()
fmt.Println("current time: ", currentTime.Hour(), ":", currentTime.Minute())
sleepHours := 0
sleepMinutes := 0
isCheckIn := true
if currentTime.Minute() <= w.CheckInMinute {
sleepMinutes = w.CheckInMinute - currentTime.Minute()
} else {
sleepMinutes = (currentTime.Minute() - w.CheckInMinute) * -1
}
if currentTime.Hour() < w.CheckInHour || (currentTime.Hour() == w.CheckInHour && currentTime.Minute() <= w.CheckInMinute) {
fmt.Println("not started day case")
sleepHours = w.CheckInHour - currentTime.Hour()
} else if currentTime.Hour() > w.CheckOutHour || (currentTime.Hour() == w.CheckOutHour && currentTime.Minute() > w.CheckOutMinute) {
fmt.Println("finished day case")
sleepHours = 24 - currentTime.Hour() + w.CheckInHour
} else {
fmt.Println("in the office case")
isCheckIn = false
sleepHours = w.CheckOutHour - currentTime.Hour()
if currentTime.Minute() <= w.CheckOutMinute {
sleepMinutes = w.CheckOutMinute - currentTime.Minute()
} else {
sleepMinutes = (currentTime.Minute() - w.CheckOutMinute) * -1
}
}
inprecission := time.Duration(rand.Intn(w.SeconsOfInprecission)-w.SeconsOfInprecission/2) * time.Second
sleepTime := time.Duration(sleepHours)*time.Hour + time.Minute*time.Duration(sleepMinutes) + inprecission
fmt.Println("Sleeping for: ", sleepTime)
time.Sleep(sleepTime)
return isCheckIn, inprecission
}