@@ -12,9 +12,16 @@ import (
12
12
"strings"
13
13
"sync"
14
14
15
- tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
15
+ telegram "github.com/go-telegram-bot-api/telegram-bot-api"
16
16
)
17
17
18
+ // TrollShieldBot aggregate the methods used by my bot to keep mocking easier
19
+ type TrollShieldBot interface {
20
+ GetChatMember (telegram.ChatConfigWithUser ) (telegram.ChatMember , error )
21
+ KickChatMember (telegram.KickChatMemberConfig ) (telegram.APIResponse , error )
22
+ Send (telegram.Chattable ) (telegram.Message , error )
23
+ }
24
+
18
25
// blacklist groups, member from that groups will be kicked automatically
19
26
var trollGroups = []string {
20
27
"@ccppbrasil" ,
@@ -31,16 +38,78 @@ const logfile = "troll-shield.log"
31
38
32
39
var log = logger .New (os .Stderr , "" , logger .LstdFlags )
33
40
34
- // findTrollHouse return the troll house group name if is well-known
35
- // otherwise, returns a empty string
36
- func findTrollHouses (bot * tgbotapi.BotAPI , userID int ) string {
41
+ // messageEvent return true if is a message event
42
+ func messageEvent (update * telegram.Update ) bool {
43
+ return update .Message != nil
44
+ }
45
+
46
+ // newChatMemberEvent return true if a new member joined to chat
47
+ func newChatMemberEvent (update * telegram.Update ) bool {
48
+ return messageEvent (update ) && update .Message .NewChatMembers != nil
49
+ }
50
+
51
+ // fromChatEvent return true if the message is from a specific chat
52
+ func fromChatEvent (update * telegram.Update , username string ) bool {
53
+ chat := update .Message .Chat
54
+ return messageEvent (update ) && chat != nil && (chat .UserName == username || chat .Title == username )
55
+ }
56
+
57
+ // getUserName return the most meaningful name available from a telegram user
58
+ // if it has a @username, return it
59
+ // if not, try to return FirstName + LastName
60
+ // otherwise, only return the FirstName
61
+ func getUserName (user telegram.User ) string {
62
+ username := user .FirstName
63
+ if user .UserName != "" {
64
+ username = fmt .Sprintf ("@%v" , user .UserName )
65
+ } else if user .LastName != "" {
66
+ username = fmt .Sprintf ("%s %s" , user .FirstName , user .LastName )
67
+ }
68
+ return username
69
+ }
70
+
71
+ func getUpdates (bot * telegram.BotAPI ) telegram.UpdatesChannel {
72
+ u := telegram .NewUpdate (0 )
73
+ u .Timeout = 60
74
+ updates , err := bot .GetUpdatesChan (u )
75
+ if err != nil {
76
+ log .Printf ("getUpdates error: %v" , err )
77
+ }
78
+
79
+ return updates
80
+ }
81
+
82
+ func reply (bot TrollShieldBot , update * telegram.Update , text string ) {
83
+ msg := telegram .NewMessage (update .Message .Chat .ID , text )
84
+ msg .ReplyToMessageID = update .Message .MessageID
85
+
86
+ _ , err := bot .Send (msg )
87
+ if err != nil {
88
+ log .Printf ("[!] Send msg failed: %v" , err )
89
+ }
90
+ }
91
+
92
+ func welcomeMessage (bot TrollShieldBot , update * telegram.Update , member telegram.User ) {
93
+ username := getUserName (member )
94
+ text := fmt .Sprintf (
95
+ `Olá %s! Seja bem-vindo ao grupo oficial de Common Lisp do Brasil.
96
+ Leia as regras em: https://lisp.com.br/rules.html.` ,
97
+ username ,
98
+ )
99
+ reply (bot , update , text )
100
+ }
101
+
102
+ // findTrollHouses return a string with groups separeted by comma,
103
+ // that groups are well-known to being troll houses.
104
+ // otherwise, if nothing is found returns a empty string
105
+ func findTrollHouses (bot TrollShieldBot , userID int ) string {
37
106
ch := make (chan string , len (trollGroups ))
38
107
var wait sync.WaitGroup
39
108
for _ , trollGroup := range trollGroups {
40
109
wait .Add (1 )
41
110
go func (group string ) {
42
111
defer wait .Done ()
43
- c , _ := bot .GetChatMember (tgbotapi .ChatConfigWithUser {
112
+ c , _ := bot .GetChatMember (telegram .ChatConfigWithUser {
44
113
SuperGroupUsername : group ,
45
114
UserID : userID ,
46
115
})
@@ -66,20 +135,29 @@ func findTrollHouses(bot *tgbotapi.BotAPI, userID int) string {
66
135
return strings .Join (houses , ", " )
67
136
}
68
137
69
- // messageEvent: return true if is a message event
70
- func messageEvent (update * tgbotapi.Update ) bool {
71
- return update .Message != nil
72
- }
73
-
74
- // newChatMemberEvent: return true if a new member joined to chat
75
- func newChatMemberEvent (update * tgbotapi.Update ) bool {
76
- return messageEvent (update ) && update .Message .NewChatMembers != nil
77
- }
78
-
79
- // fromChatEvent: return true if the message is from a specific chat
80
- func fromChatEvent (update * tgbotapi.Update , username string ) bool {
81
- chat := update .Message .Chat
82
- return messageEvent (update ) && chat != nil && (chat .UserName == username || chat .Title == username )
138
+ // kickTroll ban the troll and send a message about where we can found the trolls
139
+ func kickTroll (bot TrollShieldBot , update * telegram.Update , user telegram.User , trollHouse string ) {
140
+ chatMember := telegram.ChatMemberConfig {
141
+ ChatID : update .Message .Chat .ID ,
142
+ UserID : user .ID ,
143
+ }
144
+ resp , err := bot .KickChatMember (
145
+ telegram.KickChatMemberConfig {ChatMemberConfig : chatMember },
146
+ )
147
+
148
+ if ! resp .Ok || err != nil {
149
+ log .Printf (
150
+ "[!] Kicking %q did not work, error code %v: %v" ,
151
+ user .FirstName , resp .ErrorCode , resp .Description ,
152
+ )
153
+ } else {
154
+ username := getUserName (user )
155
+ text := fmt .Sprintf (
156
+ "%v foi banido porque é membro do grupo: %v. Adeus." ,
157
+ username , trollHouse ,
158
+ )
159
+ reply (bot , update , text )
160
+ }
83
161
}
84
162
85
163
func setupLogging () {
@@ -92,39 +170,18 @@ func setupLogging() {
92
170
93
171
log .SetOutput (wrt )
94
172
// register log to BotLoggt
95
- err = tgbotapi .SetLogger (log )
173
+ err = telegram .SetLogger (log )
96
174
if err != nil {
97
175
log .Printf ("Set Telegram Bot Logging error: %v" , err )
98
176
}
99
177
}
100
178
101
- func getUserName (user tgbotapi.User ) string {
102
- username := user .FirstName
103
- if user .UserName != "" {
104
- username = fmt .Sprintf ("@%v" , user .UserName )
105
- } else if user .LastName != "" {
106
- username = fmt .Sprintf ("%s %s" , user .FirstName , user .LastName )
107
- }
108
- return username
109
- }
110
-
111
- func reply (bot * tgbotapi.BotAPI , update * tgbotapi.Update , text string ) {
112
- msg := tgbotapi .NewMessage (update .Message .Chat .ID , text )
113
- msg .ReplyToMessageID = update .Message .MessageID
114
-
115
- _ , err := bot .Send (msg )
116
- if err != nil {
117
- log .Printf ("[!] Send msg failed: %v" , err )
118
- }
119
- }
120
-
121
- func main () {
122
- setupLogging ()
179
+ func setupBot () * telegram.BotAPI {
123
180
token , exists := os .LookupEnv ("TELEGRAM_BOT_TOKEN" )
124
181
if ! exists {
125
182
log .Fatal ("TELEGRAM_BOT_TOKEN env should be defined." )
126
183
}
127
- bot , err := tgbotapi .NewBotAPI (token )
184
+ bot , err := telegram .NewBotAPI (token )
128
185
129
186
if err != nil {
130
187
log .Panic (err )
@@ -134,12 +191,13 @@ func main() {
134
191
135
192
log .Printf ("Authorized on account @%s" , bot .Self .UserName )
136
193
137
- u := tgbotapi .NewUpdate (0 )
138
- u .Timeout = 60
139
-
140
- updates , err := bot .GetUpdatesChan (u )
194
+ return bot
195
+ }
141
196
142
- for update := range updates {
197
+ func main () {
198
+ setupLogging ()
199
+ bot := setupBot ()
200
+ for update := range getUpdates (bot ) {
143
201
if messageEvent (& update ) {
144
202
if update .Message .Text == "/lelerax" {
145
203
reply (bot , & update , "Estou vivo." )
@@ -149,37 +207,9 @@ func main() {
149
207
if newChatMemberEvent (& update ) {
150
208
for _ , member := range * update .Message .NewChatMembers {
151
209
if trollHouse := findTrollHouses (bot , member .ID ); trollHouse != "" {
152
- chatMember := tgbotapi.ChatMemberConfig {
153
- ChatID : update .Message .Chat .ID ,
154
- UserID : member .ID ,
155
- }
156
- resp , err := bot .KickChatMember (
157
- tgbotapi.KickChatMemberConfig {ChatMemberConfig : chatMember },
158
- )
159
-
160
- if resp .Ok == false || err != nil {
161
- log .Printf (
162
- "[!] Kicking %q did not work, error code %v: %v" ,
163
- member .FirstName , resp .ErrorCode , resp .Description ,
164
- )
165
- } else {
166
- username := getUserName (member )
167
- text := fmt .Sprintf (
168
- "%v foi banido porque é membro do grupo: %v. Adeus." ,
169
- username , trollHouse ,
170
- )
171
- reply (bot , & update , text )
172
- }
173
- } else {
174
- if fromChatEvent (& update , "commonlispbr" ) && ! member .IsBot {
175
- username := getUserName (member )
176
- text := fmt .Sprintf (
177
- `Olá %s! Seja bem-vindo ao grupo oficial de Common Lisp do Brasil.
178
- Leia as regras em: https://lisp.com.br/rules.html.` ,
179
- username ,
180
- )
181
- reply (bot , & update , text )
182
- }
210
+ kickTroll (bot , & update , member , trollHouse )
211
+ } else if fromChatEvent (& update , "commonlispbr" ) && ! member .IsBot {
212
+ welcomeMessage (bot , & update , member )
183
213
}
184
214
}
185
215
}
0 commit comments