Browse Source

works

master
arnaucode 7 years ago
parent
commit
ae20ff5e71
14 changed files with 413 additions and 1 deletions
  1. +32
    -0
      .gitignore
  2. +39
    -1
      README.md
  3. +22
    -0
      build/botsConfigDEMO.json
  4. BIN
      build/echo-botnet
  5. +6
    -0
      build/keywordsConfigDEMO.json
  6. +7
    -0
      build/repliesConfigDEMO.json
  7. +57
    -0
      color.go
  8. BIN
      echo-botnet
  9. +28
    -0
      main.go
  10. +54
    -0
      readConfigTokensAndConnect.go
  11. +19
    -0
      readKeywordsConfig.go
  12. +19
    -0
      readRepliesConfig.go
  13. +108
    -0
      streamTweets.go
  14. +22
    -0
      waitTime.go

+ 32
- 0
.gitignore

@ -0,0 +1,32 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
botsConfig.json
build/botsConfig.json
repliesConfig.json
keywordsConfig.json
temp
text.txt

+ 39
- 1
README.md

@ -1,2 +1,40 @@
# echo-botnet
# echo-botnet [![Go Report Card](https://goreportcard.com/badge/github.com/arnaucode/echo-botnet)](https://goreportcard.com/report/github.com/arnaucode/echo-botnet)
A twitter botnet with autonomous bots replying tweets with pre-configured replies A twitter botnet with autonomous bots replying tweets with pre-configured replies
Echo (Ēkhō): https://en.wikipedia.org/wiki/Echo_(mythology)#
Needs the files:
```
botsConfig.json --> contains the tokens of the bots
keywordsConfig.json --> contains the keywords to track from Twitter API
repliesConfig.json --> contains the replies
```
configuration file example (botsConfig.json):
```
[{
"title": "account1",
"consumer_key": "xxxxxxxxxxxxx",
"consumer_secret": "xxxxxxxxxxxxx",
"access_token_key": "xxxxxxxxxxxxx",
"access_token_secret": "xxxxxxxxxxxxx"
},
{
"title": "account2",
"consumer_key": "xxxxxxxxxxxxx",
"consumer_secret": "xxxxxxxxxxxxx",
"access_token_key": "xxxxxxxxxxxxx",
"access_token_secret": "xxxxxxxxxxxxx"
},
{
"title": "account3",
"consumer_key": "xxxxxxxxxxxxx",
"consumer_secret": "xxxxxxxxxxxxx",
"access_token_key": "xxxxxxxxxxxxx",
"access_token_secret": "xxxxxxxxxxxxx"
}
]
```

+ 22
- 0
build/botsConfigDEMO.json

@ -0,0 +1,22 @@
[{
"title": "account1",
"consumer_key": "xxxxxxxxxxxxx",
"consumer_secret": "xxxxxxxxxxxxx",
"access_token_key": "xxxxxxxxxxxxx",
"access_token_secret": "xxxxxxxxxxxxx"
},
{
"title": "account2",
"consumer_key": "xxxxxxxxxxxxx",
"consumer_secret": "xxxxxxxxxxxxx",
"access_token_key": "xxxxxxxxxxxxx",
"access_token_secret": "xxxxxxxxxxxxx"
},
{
"title": "account3",
"consumer_key": "xxxxxxxxxxxxx",
"consumer_secret": "xxxxxxxxxxxxx",
"access_token_key": "xxxxxxxxxxxxx",
"access_token_secret": "xxxxxxxxxxxxx"
}
]

BIN
build/echo-botnet


+ 6
- 0
build/keywordsConfigDEMO.json

@ -0,0 +1,6 @@
[
"word1",
"word2",
"wordToTrack3",
"word4"
]

+ 7
- 0
build/repliesConfigDEMO.json

@ -0,0 +1,7 @@
[
"Reply message 1",
"Reply message 2",
"Reply message 3",
"Hey wassup friend!",
"You like the botnet?"
]

+ 57
- 0
color.go

@ -0,0 +1,57 @@
package main
import "fmt"
//Color struct, defines the color
type Color struct{}
var c Color
//DarkGray color
func (c Color) DarkGray(t string) {
fmt.Print("\x1b[30;1m") //dark gray
fmt.Println(t)
fmt.Print("\x1b[0m") //defaultColor
}
//Red color
func (c Color) Red(t string) {
fmt.Print("\x1b[31;1m") //red
fmt.Println(t)
fmt.Print("\x1b[0m") //defaultColor
}
//Green color
func (c Color) Green(t string) {
fmt.Print("\x1b[32;1m") //green
fmt.Println(t)
fmt.Print("\x1b[0m") //defaultColor
}
//Yellow color
func (c Color) Yellow(t string) {
fmt.Print("\x1b[33;1m") //yellow
fmt.Println(t)
fmt.Print("\x1b[0m") //defaultColor
}
//Blue color
func (c Color) Blue(t string) {
fmt.Print("\x1b[34;1m") //blue
fmt.Println(t)
fmt.Print("\x1b[0m") //defaultColor
}
//Purple color
func (c Color) Purple(t string) {
fmt.Print("\x1b[35;1m") //purple
fmt.Println(t)
fmt.Print("\x1b[0m") //defaultColor
}
//Cyan color
func (c Color) Cyan(t string) {
fmt.Print("\x1b[36;1m") //cyan
fmt.Println(t)
fmt.Print("\x1b[0m") //defaultColor
}

BIN
echo-botnet


+ 28
- 0
main.go

@ -0,0 +1,28 @@
package main
import "fmt"
const version = "0.1-dev"
func main() {
c.Yellow("echo-botnet")
fmt.Println("---------------")
c.Cyan("echo-botnet initialized")
c.Purple("https://github.com/arnaucode/echo-botnet")
fmt.Println("version " + version)
keywords := readKeywordsConfig()
c.Cyan("keywords configured: ")
fmt.Println(keywords)
replies := readRepliesConfig()
c.Cyan("replies configured: ")
fmt.Println(replies)
fmt.Println("Reading botsConfig.json file")
botnet := readConfigTokensAndConnect()
c.Cyan("[list of configured bots]:")
for _, v := range botnet.ScreenNames {
c.Cyan(v)
}
streamTweets(botnet, keywords, replies)
}

+ 54
- 0
readConfigTokensAndConnect.go

@ -0,0 +1,54 @@
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"github.com/dghubble/go-twitter/twitter"
"github.com/dghubble/oauth1"
)
//Config stores the data from json botsConfig.json file
type Config struct {
Title string `json:"title"`
Consumer_key string `json:"consumer_key"`
Consumer_secret string `json:"consumer_secret"`
Access_token_key string `json:"access_token_key"`
Access_token_secret string `json:"access_token_secret"`
}
//Botnet stores each bot configured
type Botnet struct {
ScreenNames []string
Clients []*twitter.Client
}
func readConfigTokensAndConnect() (botnet Botnet) {
var config []Config
var clients []*twitter.Client
file, e := ioutil.ReadFile("botsConfig.json")
if e != nil {
fmt.Println("error:", e)
}
content := string(file)
json.Unmarshal([]byte(content), &config)
fmt.Println("botnetConfig.json read comlete")
fmt.Print("connecting to twitter api --> ")
for i := 0; i < len(config); i++ {
configu := oauth1.NewConfig(config[i].Consumer_key, config[i].Consumer_secret)
token := oauth1.NewToken(config[i].Access_token_key, config[i].Access_token_secret)
httpClient := configu.Client(oauth1.NoContext, token)
// twitter client
client := twitter.NewClient(httpClient)
clients = append(clients, client)
botnet.ScreenNames = append(botnet.ScreenNames, config[i].Title)
}
botnet.Clients = clients
fmt.Println("connection successfull")
return botnet
}

+ 19
- 0
readKeywordsConfig.go

@ -0,0 +1,19 @@
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
)
func readKeywordsConfig() []string {
var keywords []string
file, e := ioutil.ReadFile("keywordsConfig.json")
if e != nil {
fmt.Println("error:", e)
}
content := string(file)
json.Unmarshal([]byte(content), &keywords)
return keywords
}

+ 19
- 0
readRepliesConfig.go

@ -0,0 +1,19 @@
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
)
func readRepliesConfig() []string {
var replies []string
file, e := ioutil.ReadFile("repliesConfig.json")
if e != nil {
fmt.Println("error:", e)
}
content := string(file)
json.Unmarshal([]byte(content), &replies)
return replies
}

+ 108
- 0
streamTweets.go

@ -0,0 +1,108 @@
package main
import (
"fmt"
"log"
"math/rand"
"strconv"
"strings"
"time"
"github.com/dghubble/go-twitter/twitter"
)
func isRT(tweet *twitter.Tweet) bool {
tweetWords := strings.Split(tweet.Text, " ")
for i := 0; i < len(tweetWords); i++ {
if tweetWords[i] == "RT" {
return true
}
}
return false
}
func isFromOwnBot(flock Botnet, tweet *twitter.Tweet) bool {
for i := 0; i < len(flock.ScreenNames); i++ {
if flock.ScreenNames[i] == tweet.User.ScreenName {
return true
}
}
return false
}
func getRandomReplyFromReplies(replies []string) string {
rand.Seed(time.Now().UnixNano())
random := rand.Intn(len(replies))
return replies[random]
}
func replyTweet(client *twitter.Client, text string, inReplyToStatusID int64) {
tweet, httpResp, err := client.Statuses.Update(text, &twitter.StatusUpdateParams{
InReplyToStatusID: inReplyToStatusID,
})
if err != nil {
fmt.Println(err)
}
if httpResp.Status != "200 OK" {
c.Red("error: " + httpResp.Status)
c.Purple("maybe twitter has blocked the account, CTRL+C, wait 15 minutes and try again")
}
fmt.Print("tweet posted: ")
c.Green(tweet.Text)
}
func startStreaming(botnet Botnet, bot *twitter.Client, botScreenName string, keywords []string, replies []string) {
// Convenience Demux demultiplexed stream messages
demux := twitter.NewSwitchDemux()
demux.Tweet = func(tweet *twitter.Tweet) {
if isRT(tweet) == false && isFromOwnBot(botnet, tweet) == false {
//processTweet(botnetUser, botScreenName, keywords, tweet)
fmt.Println("[bot @" + botScreenName + "] - New tweet detected:")
c.Yellow(tweet.Text)
reply := getRandomReplyFromReplies(replies)
fmt.Print("reply: ")
c.Green(reply)
fmt.Println(tweet.User.ScreenName)
fmt.Println(tweet.ID)
replyTweet(bot, "@"+tweet.User.ScreenName+" "+reply, tweet.ID)
waitMinutes(1)
}
}
demux.DM = func(dm *twitter.DirectMessage) {
fmt.Println(dm.SenderID)
}
demux.Event = func(event *twitter.Event) {
fmt.Printf("%#v\n", event)
}
fmt.Println("Starting Stream...")
// FILTER
filterParams := &twitter.StreamFilterParams{
Track: keywords,
StallWarnings: twitter.Bool(true),
}
stream, err := bot.Streams.Filter(filterParams)
if err != nil {
log.Fatal(err)
}
// Receive messages until stopped or stream quits
demux.HandleChan(stream.Messages)
// Wait for SIGINT and SIGTERM (HIT CTRL-C)
/*ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
log.Println(<-ch)
fmt.Println("Stopping Stream...")
stream.Stop()*/
}
func streamTweets(botnet Botnet, keywords []string, replies []string) {
fmt.Println("total keywords: " + strconv.Itoa(len(keywords)))
c.Purple("keywords to follow: ")
fmt.Println(keywords)
c.Green("Starting to stream tweets")
for i := 0; i < len(botnet.Clients); i++ {
go startStreaming(botnet, botnet.Clients[i], botnet.ScreenNames[i], keywords, replies)
//wait 35 seconds to start the next bot
waitSeconds(35)
}
}

+ 22
- 0
waitTime.go

@ -0,0 +1,22 @@
package main
import (
"fmt"
"strconv"
"time"
)
func waitMinutes(minutes int) {
//wait to avoid the twitter api limitation
timeToSleep := time.Duration(minutes) * time.Minute
fmt.Println("waiting " + strconv.Itoa(minutes) + " min to avoid twitter api limitation")
fmt.Println(time.Now().Local())
time.Sleep(timeToSleep)
}
func waitSeconds(seconds int) {
//wait to avoid the twitter api limitation
timeToSleep := time.Duration(seconds) * time.Second
fmt.Println("waiting " + strconv.Itoa(seconds) + " seconds to avoid twitter api limitation")
fmt.Println(time.Now().Local())
time.Sleep(timeToSleep)
}

Loading…
Cancel
Save