Skip to content

Commit

Permalink
Feature: Message rate limiter
Browse files Browse the repository at this point in the history
  • Loading branch information
khades committed Jan 13, 2018
1 parent f93cd13 commit 0d3481f
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 24 deletions.
21 changes: 10 additions & 11 deletions bot/chatHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import (
"strings"
"time"

"gopkg.in/irc.v2"
"github.com/khades/servbot/commandHandlers"
"github.com/khades/servbot/ircClient"
"github.com/khades/servbot/models"
"github.com/khades/servbot/repos"
"gopkg.in/irc.v2"
)

var chatHandler irc.HandlerFunc = func(client *irc.Client, message *irc.Message) {
Expand All @@ -25,7 +25,7 @@ var chatHandler irc.HandlerFunc = func(client *irc.Client, message *irc.Message)
switch msgID {
case "subgift":
{
subHandler(message, &IrcClientInstance)
subHandler(message, IrcClientInstance)
}
case "room_mods":
{
Expand All @@ -38,12 +38,12 @@ var chatHandler irc.HandlerFunc = func(client *irc.Client, message *irc.Message)
}
case "resub":
{
subHandler(message, &IrcClientInstance)
subHandler(message, IrcClientInstance)
}

case "sub":
{
subHandler(message, &IrcClientInstance)
subHandler(message, IrcClientInstance)
}
}
}
Expand Down Expand Up @@ -92,12 +92,12 @@ var chatHandler irc.HandlerFunc = func(client *irc.Client, message *irc.Message)
IsPrime: strings.Contains(message.Tags["badges"].Encode(), "premium/1")}
repos.LogMessage(&formedMessage)
repos.DecrementAutoMessages(&formedMessage.ChannelID)

commandBody, isCommand := formedMessage.GetCommand()

isVote := strings.HasPrefix(message.Params[1], "%")
if isVote == true {
commandHandlers.Vote(true, &formedMessage, commandBody, &IrcClientInstance)
commandHandlers.Vote(true, &formedMessage, commandBody, IrcClientInstance)
}
bits, bitsFound := message.Tags.GetTag("bits")
if bitsFound {
Expand All @@ -110,17 +110,16 @@ var chatHandler irc.HandlerFunc = func(client *irc.Client, message *irc.Message)
if message.User == "khadesru" && commandBody.Command == "debugSub" {
subPlan := "2000"
sendSubMessage(&formedMessage.Channel, &formedMessage.ChannelID, &formedMessage.User, &subPlan)



}
if message.User == "khadesru" && commandBody.Command == "debugResub" {
resubCount := 3
subPlan := "2000"
sendResubMessage(&formedMessage.Channel, &formedMessage.ChannelID, &formedMessage.User, &resubCount, &subPlan)

}
handlerFunction := commandHandlers.Router.Go(commandBody.Command)
handlerFunction(true, &formedMessage, commandBody, &IrcClientInstance)
handlerFunction(true, &formedMessage, commandBody, IrcClientInstance)
}
}

Expand All @@ -131,7 +130,7 @@ var chatHandler irc.HandlerFunc = func(client *irc.Client, message *irc.Message)
for _, value := range repos.Config.Channels {
client.Write("JOIN #" + value)
}
IrcClientInstance = ircClient.IrcClient{Client: client, Bounces: make(map[string]time.Time), Ready: true, ModChannelIndex: 0}
IrcClientInstance = &ircClient.IrcClient{Client: client, Bounces: make(map[string]time.Time), Ready: true, ModChannelIndex: 0, MessageQueue: []string{}}
IrcClientInstance.SendModsCommand()
log.Println("Bot is started")
}
Expand Down
3 changes: 2 additions & 1 deletion bot/ircClientInstance.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ package bot
import "github.com/khades/servbot/ircClient"

// IrcClientInstance is concrete irc client we will work with
var IrcClientInstance = ircClient.IrcClient{Ready: false}
var IrcClientInstance = &ircClient.IrcClient{Ready: false, MessageQueue: []string{}}

2 changes: 1 addition & 1 deletion bot/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ func Start() {
clientError := chatClient.Run()
log.Println(clientError)
log.Println("Bot died...")
IrcClientInstance = ircClient.IrcClient{Ready: false}
IrcClientInstance = &ircClient.IrcClient{Ready: false, MessageQueue: []string{}}
conn.Close()
}
14 changes: 13 additions & 1 deletion index.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ func main() {

gob.Register(&models.HTTPSession{})
log.Println("Starting...")
ircClientTicker := time.NewTicker(time.Second * 3)

go func(wg *sync.WaitGroup) {
for {
wg.Add(1)
<-ircClientTicker.C
log.Println(bot.IrcClientInstance)
bot.IrcClientInstance.SendMessages(3)
wg.Done()

}
}(&wg)

modTicker := time.NewTicker(time.Second * 30)

Expand Down Expand Up @@ -132,5 +144,5 @@ func main() {

wg.Wait()
log.Println("Quitting...")

// Kseyko = PIDR
}
54 changes: 44 additions & 10 deletions ircClient/ircClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package ircClient

import (
"fmt"
"log"
"time"
"gopkg.in/irc.v2"

"github.com/khades/servbot/models"
"github.com/khades/servbot/repos"
"gopkg.in/irc.v2"
)

// IrcClient struct defines object that will send messages to a twitch server
Expand All @@ -14,10 +16,39 @@ type IrcClient struct {
Bounces map[string]time.Time
Ready bool
ModChannelIndex int
MessageQueue []string
}

// PushMessage adds message to array of messages to prevent global bans for bot
func (ircClient *IrcClient) PushMessage(message string) {
log.Println("Pushing message: ", message)
ircClient.MessageQueue = append(ircClient.MessageQueue, message)
}

// SendMessages gets slice of messages to send periodically, sends them and updates list of messages
func (ircClient *IrcClient) SendMessages(interval int) {
limit := 90
queueSliceSize := limit * interval / 60
arrayLen := len(ircClient.MessageQueue)
log.Println("Array length is", arrayLen)

if arrayLen == 0 {
return
}
if arrayLen < queueSliceSize {
queueSliceSize = arrayLen
}
messagesToSend := ircClient.MessageQueue[:queueSliceSize]
log.Println("Messages to send ", len(messagesToSend))

for _, message := range messagesToSend {
ircClient.Client.Write(message)
}
ircClient.MessageQueue = ircClient.MessageQueue[queueSliceSize:]
}

// SendDebounced prevents from sending data too frequent in public chat sending it to a PM
func (ircClient IrcClient) SendDebounced(message models.OutgoingDebouncedMessage) {
func (ircClient *IrcClient) SendDebounced(message models.OutgoingDebouncedMessage) {
key := fmt.Sprintf("%s-%s", message.Message.Channel, message.Command)
if ircClient.Bounces == nil {
ircClient.Bounces = make(map[string]time.Time)
Expand All @@ -35,27 +66,31 @@ func (ircClient IrcClient) SendDebounced(message models.OutgoingDebouncedMessage
}

// SendRaw is wrapper to Write
func (ircClient IrcClient) SendRaw(message string) {
func (ircClient *IrcClient) SendRaw(message string) {
if ircClient.Ready {
ircClient.Client.Write(message)
ircClient.PushMessage(message)
}
}

// SendPublic writes data to a specified chat
func (ircClient IrcClient) SendPublic(message *models.OutgoingMessage) {
func (ircClient *IrcClient) SendPublic(message *models.OutgoingMessage) {
if ircClient.Ready {
messageString := ""
if message.User != "" {
ircClient.Client.Write(fmt.Sprintf("PRIVMSG #%s :@%s %s", message.Channel, message.User, message.Body))
messageString = fmt.Sprintf("PRIVMSG #%s :@%s %s", message.Channel, message.User, message.Body)
} else {
ircClient.Client.Write(fmt.Sprintf("PRIVMSG #%s :%s", message.Channel, message.Body))
messageString = fmt.Sprintf("PRIVMSG #%s :%s", message.Channel, message.Body)
}
ircClient.PushMessage(messageString)
}
}

// SendPrivate writes data in private to a user
func (ircClient IrcClient) SendPrivate(message *models.OutgoingMessage) {
func (ircClient *IrcClient) SendPrivate(message *models.OutgoingMessage) {
if ircClient.Ready && message.User != "" {
ircClient.Client.Write(fmt.Sprintf("PRIVMSG #jtv :/w %s Channel %s: %s", message.User, message.Channel, message.Body))
messageString := fmt.Sprintf("PRIVMSG #jtv :/w %s Channel %s: %s", message.User, message.Channel, message.Body)
ircClient.PushMessage(messageString)

}
}

Expand All @@ -64,7 +99,6 @@ func (ircClient *IrcClient) SendModsCommand() {
channelName := repos.Config.Channels[ircClient.ModChannelIndex]
if channelName != "" {
ircClient.SendPublic(&models.OutgoingMessage{Channel: channelName, Body: "/mods"})

}
ircClient.ModChannelIndex++
if ircClient.ModChannelIndex == len(repos.Config.Channels) || ircClient.ModChannelIndex > len(repos.Config.Channels) {
Expand Down

0 comments on commit 0d3481f

Please sign in to comment.