Skip to content

Instantly share code, notes, and snippets.

@umputun
Created June 4, 2016 19:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save umputun/34ffe15f82ea1af81b57690ce735facc to your computer and use it in GitHub Desktop.
Save umputun/34ffe15f82ea1af81b57690ce735facc to your computer and use it in GitHub Desktop.
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