Passed
Push — master ( a82fbf...dd1c0a )
by Viktor
01:55
created

main.onStart   A

Complexity

Conditions 1

Size

Total Lines 6
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
package main
2
3
import (
4
	"bytes"
5
	"fmt"
6
	"net/http"
7
	"net/url"
8
	"os"
9
	"os/signal"
10
	"strings"
11
	"syscall"
12
	"time"
13
14
	"gopkg.in/robfig/cron.v2"
15
16
	"github.com/FlameInTheDark/dtbot/bot"
17
	"github.com/FlameInTheDark/dtbot/cmd"
18
	"github.com/bwmarrin/discordgo"
19
)
20
21
var (
22
	conf *bot.Config
23
	// CmdHandler bot command handler
24
	CmdHandler *bot.CommandHandler
25
	// Sessions bot session manager
26
	Sessions        *bot.SessionManager
27
	botId           string
0 ignored issues
show
introduced by
var botId should be botID
Loading history...
28
	youtube         *bot.Youtube
29
	botMsg          *bot.BotMessages
30
	dataType        *bot.DataType
31
	dbWorker        *bot.DBWorker
32
	guilds          bot.GuildsMap
33
	botCron         *cron.Cron
34
	twitch          *bot.Twitch
35
	messagesCounter int
36
)
37
38
func main() {
39
	botCron = cron.New()
40
	conf = bot.LoadConfig()
41
	CmdHandler = bot.NewCommandHandler()
42
	registerCommands()
43
	Sessions = bot.NewSessionManager()
44
	youtube = &bot.Youtube{Conf: conf}
45
	botMsg = bot.NewMessagesMap()
46
	dataType = bot.NewDataType()
47
	discord, err := discordgo.New("Bot " + os.Getenv("BOT_TOKEN"))
48
	if err != nil {
49
		fmt.Println("Create session error, ", err)
50
		return
51
	}
52
	usr, err := discord.User("@me")
53
	if err != nil {
54
		fmt.Println("Error obtaining account details,", err)
55
		return
56
	}
57
	botId = usr.ID
58
	discord.AddHandler(func(discord *discordgo.Session, ready *discordgo.Ready) {
59
		_ = discord.UpdateStatus(0, conf.General.Game)
60
		guilds := discord.State.Guilds
61
		fmt.Println("Ready with", len(guilds), "guilds.")
62
	})
63
64
	err = discord.Open()
65
	if err != nil {
66
		fmt.Printf("Connection open error: %v", err)
67
		return
68
	}
69
	defer discord.Close()
70
	fmt.Println("Bot is now running.")
71
72
	sc := make(chan os.Signal, 1)
73
	signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
74
	dbWorker = bot.NewDBSession(conf.General.DatabaseName)
75
	guilds = dbWorker.InitGuilds(discord, conf)
76
	botCron.Start()
77
	defer botCron.Stop()
78
	defer dbWorker.DBSession.Close()
79
	twitch = bot.TwitchInit(discord, conf, dbWorker)
80
	go MetricsSender(discord)
81
	// Init command handler
82
	discord.AddHandler(commandHandler)
83
	onStart()
84
	<-sc
85
}
86
87
// Handle discord messages
88
func commandHandler(discord *discordgo.Session, message *discordgo.MessageCreate) {
89
	messagesCounter++
90
	user := message.Author
91
	if user.ID == botId || user.Bot {
92
		return
93
	}
94
	args := strings.Split(message.Content, " ")
95
	name := strings.ToLower(args[0])
96
	command, found := CmdHandler.Get(name)
97
	if !found {
98
		return
99
	}
100
101
	var permission = true
102
	var msg string
103
	// Checking permissions
104
	perm, err := discord.State.UserChannelPermissions(botId, message.ChannelID)
105
	if err != nil {
106
		msg = fmt.Sprintf("Error whilst getting bot permissions %v\n", err)
107
		permission = false
108
	} else {
109
		if perm&discordgo.PermissionSendMessages != discordgo.PermissionSendMessages ||
110
			perm&discordgo.PermissionAttachFiles != discordgo.PermissionAttachFiles {
111
			msg = "Permissions denied"
112
			permission = false
113
		}
114
	}
115
116
	channel, err := discord.State.Channel(message.ChannelID)
117
	if err != nil {
118
		fmt.Println("Error getting channel,", err)
119
		return
120
	}
121
	guild, err := discord.State.Guild(channel.GuildID)
122
	if err != nil {
123
		fmt.Println("Error getting guild,", err)
124
		return
125
	}
126
127
	if permission {
128
		ctx := bot.NewContext(
129
			botId,
130
			discord,
131
			guild,
132
			channel,
133
			user,
134
			message,
135
			conf,
136
			CmdHandler,
137
			Sessions,
138
			youtube,
139
			botMsg,
140
			dataType,
141
			dbWorker,
142
			guilds,
143
			botCron,
144
			twitch)
145
		ctx.Args = args[1:]
146
		c := *command
147
		c(*ctx)
148
	} else {
149
		dbWorker.Log("Message", guild.ID, msg)
150
		query := []byte(fmt.Sprintf("logs,server=%v module=\"%v\"", guild.ID, "message"))
151
		addr := fmt.Sprintf("%v/write?db=%v", conf.Metrics.Address, conf.Metrics.Database)
152
		r := bytes.NewReader(query)
153
		_, _ = http.Post(addr, "", r)
154
	}
155
}
156
157
// Adds bot commands
158
func registerCommands() {
159
	CmdHandler.Register("!r", cmd.PlayerCommand)
160
	CmdHandler.Register("!w", cmd.WeatherCommand)
161
	CmdHandler.Register("!t", cmd.TranslateCommand)
162
	CmdHandler.Register("!n", cmd.NewsCommand)
163
	CmdHandler.Register("!c", cmd.CurrencyCommand)
164
	CmdHandler.Register("!y", cmd.YoutubeCommand)
165
	CmdHandler.Register("!v", cmd.VoiceCommand)
166
	CmdHandler.Register("!b", cmd.BotCommand)
167
	CmdHandler.Register("!play", cmd.YoutubeShortCommand)
168
	CmdHandler.Register("!d", cmd.DebugCommand)
169
	CmdHandler.Register("!p", cmd.PollCommand)
170
	CmdHandler.Register("!m", cmd.YandexmapCommand)
171
	CmdHandler.Register("!dice", cmd.DiceCommand)
172
	CmdHandler.Register("!help", cmd.HelpCommand)
173
	CmdHandler.Register("!cron", cmd.CronCommand)
174
	CmdHandler.Register("!geoip", cmd.GeoIPCommand)
175
	CmdHandler.Register("!twitch", cmd.TwitchCommand)
176
}
177
178
// MetricsSender sends metrics to InfluxDB and another services
179
func MetricsSender(d *discordgo.Session) {
180
	for {
181
		go twitch.Update()
182
183
		// Calculating users count
184
		usersCount := 0
185
		for _, g := range d.State.Guilds {
186
			usersCount += len(g.Members)
187
		}
188
189
		// Metrics counters
190
		queryCounters := []byte(fmt.Sprintf("counters guilds=%v,messages=%v,users=%v", len(d.State.Guilds), messagesCounter, usersCount))
191
		addrCounters := fmt.Sprintf("%v/write?db=%v&u=%v&p=%v",
192
			conf.Metrics.Address, conf.Metrics.Database, conf.Metrics.User, conf.Metrics.Password)
193
		rCounters := bytes.NewReader(queryCounters)
194
		_, _ = http.Post(addrCounters, "", rCounters)
195
196
		// Bot lists
197
		if conf.DBL.Token != "" {
198
			sendDBL(conf.DBL.BotID, conf.DBL.Token, len(d.State.Guilds))
199
		}
200
		messagesCounter = 0
201
		time.Sleep(time.Minute)
202
	}
203
}
204
205
func sendDBL(botID, token string, guilds int) {
206
	timeout := time.Duration(time.Duration(1) * time.Second)
207
	client := &http.Client{
208
		Timeout: time.Duration(timeout),
209
	}
210
	query := url.Values{}
211
	query.Add("server_count", fmt.Sprintf("%v", guilds))
212
	req, _ := http.NewRequest("POST",
213
		fmt.Sprintf("https://discordbots.org/api/bots/%v/stats",
214
			botID), strings.NewReader(query.Encode()))
215
	req.Header.Add("Authorization", token)
216
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
217
	_,_ = client.Do(req)
218
}
219
220
func onStart() {
221
	queryCounters := []byte(fmt.Sprintf("starts value=1"))
222
	addrCounters := fmt.Sprintf("%v/write?db=%v&u=%v&p=%v",
223
		conf.Metrics.Address, conf.Metrics.Database, conf.Metrics.User, conf.Metrics.Password)
224
	rCounters := bytes.NewReader(queryCounters)
225
	_, _ = http.Post(addrCounters, "", rCounters)
226
}