Passed
Push — master ( 5d908c...87bfc6 )
by Viktor
01:59
created

main.joinHandler   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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