Passed
Push — master ( fb45c9...d2824e )
by Viktor
01:30
created

main.guildAddHandler   A

Complexity

Conditions 2

Size

Total Lines 16
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 14
nop 2
dl 0
loc 16
rs 9.7
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(guildAddHandler)
83
	discord.AddHandler(commandHandler)
84
	discord.AddHandler(joinHandler)
85
	onStart()
86
	<-sc
87
}
88
89
func joinHandler(discord *discordgo.Session, e *discordgo.GuildMemberAdd) {
90
	if _, ok := guilds.Guilds[e.GuildID]; !ok {
91
		guilds.Guilds[e.GuildID] = &bot.GuildData{
92
			ID:          e.GuildID,
93
			WeatherCity: conf.Weather.City,
94
			NewsCounty:  conf.News.Country,
95
			Language:    conf.General.Language,
96
			Timezone:    conf.General.Timezone,
97
			EmbedColor:  conf.General.EmbedColor,
98
			VoiceVolume: conf.Voice.Volume,
99
			Greeting:    "",
100
		}
101
	} else {
102
		bot.Greeting(discord, e, guilds.Guilds[e.GuildID], conf)
103
	}
104
}
105
106
func guildAddHandler(discord *discordgo.Session, e *discordgo.GuildCreate) {
107
	if _, ok := guilds.Guilds[e.ID]; !ok {
108
		guilds.Guilds[e.ID] = &bot.GuildData{
109
			ID:          e.ID,
110
			WeatherCity: conf.Weather.City,
111
			NewsCounty:  conf.News.Country,
112
			Language:    conf.General.Language,
113
			Timezone:    conf.General.Timezone,
114
			EmbedColor:  conf.General.EmbedColor,
115
			VoiceVolume: conf.Voice.Volume,
116
			Greeting:    "",
117
		}
118
	}
119
	emb := bot.NewEmbed("").
120
		Field(conf.GetLocaleLang("bot_joined_title", guilds.Guilds[e.ID].Language), conf.GetLocaleLang("bot_joined_text", guilds.Guilds[e.ID].Language), false)
121
	_, _ = discord.ChannelMessageSendEmbed(e.OwnerID, emb.GetEmbed())
122
}
123
124
// Handle discord messages
125
func commandHandler(discord *discordgo.Session, message *discordgo.MessageCreate) {
126
	messagesCounter++
127
	user := message.Author
128
	if user.ID == botId || user.Bot {
129
		return
130
	}
131
	args := strings.Split(message.Content, " ")
132
	name := strings.ToLower(args[0])
133
	command, found := CmdHandler.Get(name)
134
	if !found {
135
		return
136
	}
137
138
	var permission = true
139
	var msg string
140
	// Checking permissions
141
	perm, err := discord.State.UserChannelPermissions(botId, message.ChannelID)
142
	if err != nil {
143
		msg = fmt.Sprintf("Error whilst getting bot permissions %v\n", err)
144
		permission = false
145
	} else {
146
		if perm&discordgo.PermissionSendMessages != discordgo.PermissionSendMessages ||
147
			perm&discordgo.PermissionAttachFiles != discordgo.PermissionAttachFiles {
148
			msg = "Permissions denied"
149
			permission = false
150
		}
151
	}
152
153
	channel, err := discord.State.Channel(message.ChannelID)
154
	if err != nil {
155
		fmt.Println("Error getting channel,", err)
156
		return
157
	}
158
	guild, err := discord.State.Guild(channel.GuildID)
159
	if err != nil {
160
		fmt.Println("Error getting guild,", err)
161
		return
162
	}
163
164
	if permission {
165
		ctx := bot.NewContext(
166
			botId,
167
			discord,
168
			guild,
169
			channel,
170
			user,
171
			message,
172
			conf,
173
			CmdHandler,
174
			Sessions,
175
			youtube,
176
			botMsg,
177
			dataType,
178
			dbWorker,
179
			guilds,
180
			botCron,
181
			twitch)
182
		ctx.Args = args[1:]
183
		c := *command
184
		c(*ctx)
185
	} else {
186
		dbWorker.Log("Message", guild.ID, msg)
187
		query := []byte(fmt.Sprintf("logs,server=%v module=\"%v\"", guild.ID, "message"))
188
		addr := fmt.Sprintf("%v/write?db=%v", conf.Metrics.Address, conf.Metrics.Database)
189
		r := bytes.NewReader(query)
190
		_, _ = http.Post(addr, "", r)
191
	}
192
}
193
194
// Adds bot commands
195
func registerCommands() {
196
	CmdHandler.Register("!r", cmd.PlayerCommand)
197
	CmdHandler.Register("!w", cmd.WeatherCommand)
198
	CmdHandler.Register("!t", cmd.TranslateCommand)
199
	CmdHandler.Register("!n", cmd.NewsCommand)
200
	CmdHandler.Register("!c", cmd.CurrencyCommand)
201
	CmdHandler.Register("!y", cmd.YoutubeCommand)
202
	CmdHandler.Register("!v", cmd.VoiceCommand)
203
	CmdHandler.Register("!b", cmd.BotCommand)
204
	CmdHandler.Register("!play", cmd.YoutubeShortCommand)
205
	CmdHandler.Register("!d", cmd.DebugCommand)
206
	CmdHandler.Register("!p", cmd.PollCommand)
207
	CmdHandler.Register("!m", cmd.YandexmapCommand)
208
	CmdHandler.Register("!dice", cmd.DiceCommand)
209
	CmdHandler.Register("!help", cmd.HelpCommand)
210
	CmdHandler.Register("!cron", cmd.CronCommand)
211
	CmdHandler.Register("!geoip", cmd.GeoIPCommand)
212
	CmdHandler.Register("!twitch", cmd.TwitchCommand)
213
}
214
215
// MetricsSender sends metrics to InfluxDB and another services
216
func MetricsSender(d *discordgo.Session) {
217
	for {
218
		go twitch.Update()
219
220
		// Calculating users count
221
		usersCount := 0
222
		for _, g := range d.State.Guilds {
223
			usersCount += len(g.Members)
224
		}
225
226
		// Metrics counters
227
		queryCounters := []byte(fmt.Sprintf("counters guilds=%v,messages=%v,users=%v", len(d.State.Guilds), messagesCounter, usersCount))
228
		addrCounters := fmt.Sprintf("%v/write?db=%v&u=%v&p=%v",
229
			conf.Metrics.Address, conf.Metrics.Database, conf.Metrics.User, conf.Metrics.Password)
230
		rCounters := bytes.NewReader(queryCounters)
231
		_, _ = http.Post(addrCounters, "", rCounters)
232
233
		// Bot lists
234
		if conf.DBL.Token != "" {
235
			sendDBL(conf.DBL.BotID, conf.DBL.Token, len(d.State.Guilds))
236
		}
237
		messagesCounter = 0
238
		time.Sleep(time.Minute)
239
	}
240
}
241
242
func sendDBL(botID, token string, guilds int) {
243
	timeout := time.Duration(time.Duration(1) * time.Second)
244
	client := &http.Client{
245
		Timeout: time.Duration(timeout),
246
	}
247
	query := url.Values{}
248
	query.Add("server_count", fmt.Sprintf("%v", guilds))
249
	req, _ := http.NewRequest("POST",
250
		fmt.Sprintf("https://discordbots.org/api/bots/%v/stats",
251
			botID), strings.NewReader(query.Encode()))
252
	req.Header.Add("Authorization", token)
253
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
254
	_, _ = client.Do(req)
255
}
256
257
func onStart() {
258
	queryCounters := []byte(fmt.Sprintf("starts value=1"))
259
	addrCounters := fmt.Sprintf("%v/write?db=%v&u=%v&p=%v",
260
		conf.Metrics.Address, conf.Metrics.Database, conf.Metrics.User, conf.Metrics.Password)
261
	rCounters := bytes.NewReader(queryCounters)
262
	_, _ = http.Post(addrCounters, "", rCounters)
263
}
264