-
-
Save umputun/34ffe15f82ea1af81b57690ce735facc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package events | |
import ( | |
"bytes" | |
"fmt" | |
"log" | |
"net/http" | |
"time" | |
"github.com/sromku/go-gitter" | |
) | |
type banActivity struct { | |
dt time.Time | |
count int | |
} | |
//AutoBan reacts on unusaully long messages and too-many-per-sec kind of activity. | |
//It doesn't use gitter module (ban not supported by go-gitter) but sends ban POST command directly to API | |
type AutoBan struct { | |
GitterToken string | |
RoomID string | |
MaxMsgSize int | |
MsgsPerSec int | |
lastActivity map[gitter.User]banActivity | |
} | |
//check activity for bad patterns. not thread-safe | |
func (a *AutoBan) check(msg gitter.Message) bool { | |
if a.lastActivity == nil { | |
a.lastActivity = make(map[gitter.User]banActivity) | |
} | |
if len(msg.Text) > a.MaxMsgSize { | |
log.Printf("triggred ban due size, %v", msg.From) | |
a.ban(msg.From) | |
return true | |
} | |
if act, found := a.lastActivity[msg.From]; found { | |
if act.count >= a.MsgsPerSec { | |
log.Printf("triggred ban due activity, %v", msg.From) | |
a.ban(msg.From) | |
return true | |
} | |
if time.Now().Before(act.dt.Add(time.Second)) { | |
act.dt = time.Now() | |
act.count++ | |
a.lastActivity[msg.From] = act | |
log.Printf("same-second message from %s, count=%d", msg.From.Username, act.count) | |
return false | |
} | |
} | |
a.lastActivity[msg.From] = banActivity{dt: time.Now(), count: 1} | |
return false | |
} | |
//ban API undocumented, based on https://github.com/gitterHQ/gitter/issues/989#issuecomment-163594444 | |
func (a *AutoBan) ban(user gitter.User) { | |
log.Printf("autoban for %s/%s", user.Username, user.DisplayName) | |
banUser := []byte(fmt.Sprintf("{\"username\": \"%s\"}", user.Username)) | |
req, err := http.NewRequest("POST", fmt.Sprintf("https://gitter.im/api/v1/rooms/%s/bans?access_token=%s", | |
a.RoomID, a.GitterToken), bytes.NewBuffer(banUser)) | |
if err != nil { | |
log.Printf("failed to make request to ban %s, error=%v", user.Username, err) | |
return | |
} | |
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", a.GitterToken)) | |
client := &http.Client{} | |
resp, err := client.Do(req) | |
if err != nil { | |
log.Printf("failed to send ban request, %v", err) | |
return | |
} | |
log.Printf("ban status for %s - %s", user.Username, resp.Status) | |
resp.Body.Close() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment