/
main.go
235 lines (201 loc) · 5.77 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
235
package main
import (
"fmt"
"log"
"net/http"
"strings"
"github.com/meinside/scroll-daemon/lib"
"github.com/meinside/rpi-tools/status"
scroll "github.com/meinside/scrollphat-go"
bot "github.com/meinside/telegram-bot-go"
)
const (
httpCommandPath = "/"
queueSize = 1
locationLivePeriodSeconds = 60
)
// variables
var pHat *scroll.ScrollPHat
var apiToken string
var localPort int
var availableIds []string
var pHatBrightness byte
var pHatScrollDelay uint
var pHatRotateOrNot bool
var telegramMonitorInterval uint
var isVerbose bool
var queue chan string
var allKeyboards [][]bot.KeyboardButton
func init() {
// read variables from config file
if conf, err := lib.GetConfig(); err == nil {
apiToken = conf.ApiToken
localPort = conf.LocalPort
availableIds = conf.AvailableIds
pHatBrightness = conf.PHatBrightness
pHatScrollDelay = conf.PHatScrollDelay
pHatRotateOrNot = conf.PHatRotate180Degrees
telegramMonitorInterval = conf.TelegramMonitorInterval
isVerbose = conf.IsVerbose
// all keyboard buttons
allKeyboards = [][]bot.KeyboardButton{
[]bot.KeyboardButton{
bot.KeyboardButton{
Text: "/" + lib.CommandTime,
},
bot.KeyboardButton{
Text: "/" + lib.CommandIP,
},
bot.KeyboardButton{
Text: "/" + lib.CommandHelp,
},
},
}
// initialize other variables
queue = make(chan string, queueSize)
} else {
panic(err.Error())
}
}
// check if given Telegram id is available
func isAvailableId(id string) bool {
for _, v := range availableIds {
if v == id {
return true
}
}
return false
}
// for processing incoming update from Telegram
func processUpdate(b *bot.Bot, update bot.Update) bool {
// check username
var userId string
if update.Message.From.Username == nil {
log.Printf("*** Not allowed (no user name): %s", update.Message.From.FirstName)
return false
}
userId = *update.Message.From.Username
if !isAvailableId(userId) {
log.Printf("*** Id not allowed: %s", userId)
return false
}
if update.HasMessage() {
txt := *update.Message.Text
if isVerbose {
log.Printf("received telegram message: %s", txt)
}
if strings.HasPrefix(txt, "/") { // if it is command,
var options map[string]interface{} = map[string]interface{}{
"reply_markup": bot.ReplyKeyboardMarkup{
Keyboard: allKeyboards,
ResizeKeyboard: true,
},
}
if strings.HasPrefix(txt, "/"+lib.CommandStart) {
message := lib.MessageStart
// send message
if sent := b.SendMessage(update.Message.Chat.ID, message, options); !sent.Ok {
log.Printf("*** Failed to send message: %s", *sent.Description)
}
} else if strings.HasPrefix(txt, "/"+lib.CommandTime) {
time := lib.GetTimeString()
queue <- time
if sent := b.SendMessage(update.Message.Chat.ID, time, options); !sent.Ok {
log.Printf("*** Failed to send message: %s", *sent.Description)
}
} else if strings.HasPrefix(txt, "/"+lib.CommandIP) {
ip := strings.Join(status.IpAddresses(), ", ")
queue <- ip
if sent := b.SendMessage(update.Message.Chat.ID, ip, options); !sent.Ok {
log.Printf("*** Failed to send message: %s", *sent.Description)
}
} else if strings.HasPrefix(txt, "/"+lib.CommandHelp) {
// send message
message := lib.MessageHelp
if sent := b.SendMessage(update.Message.Chat.ID, message, options); !sent.Ok {
log.Printf("*** Failed to send message: %s", *sent.Description)
}
} else {
log.Printf("*** No such command: %s", txt)
// send message
message := fmt.Sprintf("No such command: %s", txt)
if sent := b.SendMessage(update.Message.Chat.ID, message, options); !sent.Ok {
log.Printf("*** Failed to send message: %s", *sent.Description)
}
}
} else { // otherwise,
queue <- txt
}
}
return false
}
// for processing incoming request through HTTP
var httpHandler = func(w http.ResponseWriter, r *http.Request) {
command := r.FormValue(lib.ParamCommand)
value := r.FormValue(lib.ParamValue)
if isVerbose {
log.Printf("received http command: %s, value: %s", command, value)
}
if command != "" { // if it is command,
if command == lib.CommandTime {
queue <- lib.GetTimeString()
} else if command == lib.CommandIP {
queue <- strings.Join(status.IpAddresses(), ", ")
} else {
log.Printf("*** No such command: %s", command)
}
} else { // otherwise,
queue <- value
}
}
func main() {
client := bot.NewClient(apiToken)
client.Verbose = isVerbose
pHat = scroll.New()
if pHat == nil {
panic("Failed to initialize Scroll pHat")
} else {
// setup pHat
scroll.IsFlippedHorizontally = pHatRotateOrNot
scroll.IsFlippedVertically = pHatRotateOrNot
pHat.SetBrightness(pHatBrightness)
// wait for channel
go func() {
for {
select {
case s := <-queue:
pHat.Scroll(s, pHatScrollDelay)
}
}
}()
// start web server
go func() {
log.Printf("Starting local web server on port: %d", localPort)
http.HandleFunc(httpCommandPath, httpHandler)
if err := http.ListenAndServe(fmt.Sprintf(":%d", localPort), nil); err != nil {
panic(err.Error())
}
}()
// monitor for new telegram updates
if me := client.GetMe(); me.Ok { // get info about this bot
log.Printf("Launching bot: @%s (%s)", *me.Result.Username, me.Result.FirstName)
// delete webhook (getting updates will not work when wehbook is set up)
if unhooked := client.DeleteWebhook(); unhooked.Ok {
// wait for new updates
client.StartMonitoringUpdates(0, int(telegramMonitorInterval), func(b *bot.Bot, update bot.Update, err error) {
if err == nil {
if update.Message != nil {
processUpdate(b, update)
}
} else {
log.Printf("*** Error while receiving update (%s)", err.Error())
}
})
} else {
panic("Failed to delete webhook")
}
} else {
panic("Failed to get info of the bot")
}
}
}