Skip to content

Commit

Permalink
Add /kills command with save state functionality (#4)
Browse files Browse the repository at this point in the history
* Add /kills command with save state functionality

CHANGELOG:

- Kills state it's loaded at session start, if doesn't exists set to 0.
- Kills state it's saved on the file kills.txt
- Kills state it's saved after each ban, to ensure being saved.
- If /kills it's called will report the current kills state.

* Add unit tests

* Improve test coverage on edge cases: fix some behaviors too

Important fix: os.O_TRUNC should be set as flag in os.OpenFile to
overwrite the kills.txt file properly.

Otherwise, ff the kills.txt had initially "random-fuckups", writing 10
will turn out in: "10ndom-fuckups".

This is not the intended behavior.

* Separate main function in main.go and mark as !test

This will make more easier to control the unit tests, since main is
not possible to test.
  • Loading branch information
ryukinix committed Aug 6, 2020
1 parent fd460de commit 7015110
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
- name: Calc coverage
run: |
export PATH=$PATH:$(go env GOPATH)/bin
go test -v -covermode=count -coverprofile=coverage.out
go test -v -covermode=count -tags test -coverprofile=coverage.out
- name: Convert coverage to lcov
uses: jandelgado/gcov2lcov-action@v1.0.0
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
/troll-shield

*.log
/kills.txt
63 changes: 63 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//+build !test
// Copyright 2020 the commonlispbr authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
"strings"
)

func main() {
setupLogging()
bot, botHidden, err := setupBots()
if err != nil {
log.Fatal(err.Error())
}
kills := loadKills(killsFile)
log.Printf("Currently kill state: %v", kills)

for update := range getUpdates(bot) {
if messageEvent(&update) {
if update.Message.Text == "/lelerax" {
reply(bot, &update, "Estou vivo.")
}

if update.Message.Text == "/kills" {
reportKills(bot, &update, kills)
}

// Exit automatically from group after the bot receive a message from it
for _, trollGroup := range trollGroups {
if fromChatEvent(&update, strings.TrimLeft(trollGroup, "@")) {
leaveChat(bot, &update, trollGroup)
}
}
}

if newChatMemberEvent(&update) {
for _, member := range *update.Message.NewChatMembers {
if trollHouse := findTrollHouses(botHidden, member.ID); trollHouse != "" {
err := kickTroll(bot, &update, member, trollHouse)
if err == nil {
kills++
if err := saveKills(killsFile, kills); err != nil {
log.Printf("saving kills failed: %v", err)
}
}
} else if fromChatEvent(&update, "commonlispbr") && !member.IsBot {
welcomeMessage(bot, &update, member)
}

// Exit automatically from groups when I'm joining it
for _, trollGroup := range trollGroups {
if fromChatEvent(&update, strings.TrimLeft(trollGroup, "@")) && member.UserName == bot.Self.UserName {
leaveChat(bot, &update, trollGroup)
}
}

}
}
}
}
67 changes: 32 additions & 35 deletions troll_shield.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ package main
import (
"fmt"
"io"
"io/ioutil"
logger "log"
"os"
"strconv"
"strings"
"sync"

Expand Down Expand Up @@ -38,6 +40,7 @@ var trollGroups = []string{
}

const logfile = "troll-shield.log"
const killsFile = "kills.txt"

var log = logger.New(os.Stderr, "", logger.LstdFlags)

Expand Down Expand Up @@ -139,7 +142,7 @@ func findTrollHouses(bot TrollShieldBot, userID int) string {
}

// kickTroll ban the troll and send a message about where we can found the trolls
func kickTroll(bot TrollShieldBot, update *telegram.Update, user telegram.User, trollHouse string) {
func kickTroll(bot TrollShieldBot, update *telegram.Update, user telegram.User, trollHouse string) error {
chatMember := telegram.ChatMemberConfig{
ChatID: update.Message.Chat.ID,
UserID: user.ID,
Expand All @@ -161,6 +164,8 @@ func kickTroll(bot TrollShieldBot, update *telegram.Update, user telegram.User,
)
reply(bot, update, text)
}

return err
}

func setupLogging() {
Expand Down Expand Up @@ -229,43 +234,35 @@ func leaveChat(bot TrollShieldBot, update *telegram.Update, trollGroup string) {
}
}

func main() {
setupLogging()
bot, botHidden, err := setupBots()
if err != nil {
log.Fatal(err.Error())
func loadKills(fpath string) int64 {
dat, err := ioutil.ReadFile(fpath)
if err == nil {
i, err := strconv.Atoi(strings.TrimSpace(string(dat)))
if err != nil {
log.Printf("Parsing %q go bad, got error: %v", fpath, err)
} else {
return int64(i)
}
}

for update := range getUpdates(bot) {
if messageEvent(&update) {
if update.Message.Text == "/lelerax" {
reply(bot, &update, "Estou vivo.")
}

// Exit automatically from group after the bot receive a message from it
for _, trollGroup := range trollGroups {
if fromChatEvent(&update, strings.TrimLeft(trollGroup, "@")) {
leaveChat(bot, &update, trollGroup)
}
}
}
return 0
}

if newChatMemberEvent(&update) {
for _, member := range *update.Message.NewChatMembers {
if trollHouse := findTrollHouses(botHidden, member.ID); trollHouse != "" {
kickTroll(bot, &update, member, trollHouse)
} else if fromChatEvent(&update, "commonlispbr") && !member.IsBot {
welcomeMessage(bot, &update, member)
}

// Exit automatically from groups when I'm joining it
for _, trollGroup := range trollGroups {
if fromChatEvent(&update, strings.TrimLeft(trollGroup, "@")) && member.UserName == bot.Self.UserName {
leaveChat(bot, &update, trollGroup)
}
}
func saveKills(fpath string, kills int64) error {
f, err := os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
if err == nil {
_, err = f.WriteString(strconv.FormatInt(kills, 10))
}
if e := f.Close(); e != nil {
err = e
}
return err
}

}
}
func reportKills(bot TrollShieldBot, update *telegram.Update, kills int64) {
txt := fmt.Sprintf("%v foram sacrificados.", kills)
if kills%2 == 0 {
txt = fmt.Sprintf("Já taquei o pau em %v trolls!", kills)
}
reply(bot, update, txt)
}
54 changes: 52 additions & 2 deletions troll_shield_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"errors"
"io/ioutil"
"os"
"testing"

Expand Down Expand Up @@ -142,9 +143,13 @@ func TestKickTroll(t *testing.T) {
message.Chat = &chat
update.Message = &message
user := telegram.User{}
kickTroll(&botnilson, &update, user, "@trollhouse")
if err := kickTroll(&botnilson, &update, user, "@trollhouse"); err != nil {
t.Errorf("kickTroll error: %v", err)
}
user.ID = 1
kickTroll(&botnilson, &update, user, "@trollhouse")
if err := kickTroll(&botnilson, &update, user, "@trollhouse"); err == nil {
t.Errorf("kickTroll should fail, but got: %v", err)
}
}

func TestWelcomeMessage(t *testing.T) {
Expand Down Expand Up @@ -202,3 +207,48 @@ func TestGetUpdates(t *testing.T) {
bot := BotMockup{}
getUpdates(&bot)
}

func TestSaveLoadKills(t *testing.T) {
tmpfile, err := ioutil.TempFile("", "kills.txt")
if err != nil {
t.Fatal(err)
}
content := []byte("isso-nao-eh-um-numero")
if _, err := tmpfile.Write(content); err != nil {
t.Fatal(err)
}

if kills := loadKills(tmpfile.Name()); kills != 0 {
t.Errorf("loadKills should return 0 when there is a invalid number, got: %v", kills)
}

// write 10
if err := saveKills(tmpfile.Name(), 10); err != nil {
t.Errorf("saveKills failed: %v", err)
}

// read 10
if kills := loadKills(tmpfile.Name()); kills != 10 {
t.Errorf("Save/Load of KillCounter didn't worked, expected 10, got %v", kills)
}

if err := tmpfile.Close(); err != nil {
t.Fatal(err)
}

if err := os.Remove(tmpfile.Name()); err != nil {
t.Fatal(err)
}

}

func TestReportKills(t *testing.T) {
bot := BotMockup{}
update := telegram.Update{}
message := telegram.Message{}
chat := telegram.Chat{}
message.Chat = &chat
update.Message = &message
reportKills(&bot, &update, int64(11))
reportKills(&bot, &update, int64(10))
}

0 comments on commit 7015110

Please sign in to comment.