Completed
Push — master ( cb5d8b...ad7957 )
by Viktor
01:46
created
Severity
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
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
	albUpdater      *bot.AlbionUpdater
36
	blacklist       *bot.BlackListStruct
37
	messagesCounter int
38
)
39
40
func main() {
41
	botCron = cron.New()
42
	conf = bot.LoadConfig()
43
	CmdHandler = bot.NewCommandHandler()
44
	registerCommands()
45
	Sessions = bot.NewSessionManager()
46
	youtube = &bot.Youtube{Conf: conf}
47
	botMsg = bot.NewMessagesMap()
48
	dataType = bot.NewDataType()
49
	discord, err := discordgo.New("Bot " + os.Getenv("BOT_TOKEN"))
50
	if err != nil {
51
		fmt.Println("Create session error, ", err)
52
		return
53
	}
54
	usr, err := discord.User("@me")
55
	if err != nil {
56
		fmt.Println("Error obtaining account details,", err)
57
		return
58
	}
59
	botId = usr.ID
60
	discord.AddHandler(func(discord *discordgo.Session, ready *discordgo.Ready) {
61
		_ = discord.UpdateStatus(0, conf.General.Game)
62
		guilds := discord.State.Guilds
63
		fmt.Println("Ready with", len(guilds), "guilds.")
64
	})
65
66
	err = discord.Open()
67
	if err != nil {
68
		fmt.Printf("Connection open error: %v", err)
69
		return
70
	}
71
	defer discord.Close()
72
	fmt.Println("Bot is now running.")
73
74
	sc := make(chan os.Signal, 1)
75
	signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
76
	dbWorker = bot.NewDBSession(conf.General.DatabaseName)
77
	guilds = dbWorker.InitGuilds(discord, conf)
78
	botCron.Start()
79
	defer botCron.Stop()
80
	defer dbWorker.DBSession.Close()
81
	twitch = bot.TwitchInit(discord, conf, dbWorker)
82
	albUpdater = bot.AlbionGetUpdater(dbWorker)
83
	blacklist = dbWorker.GetBlacklist()
84
	go BotUpdater(discord)
85
	// Init command handler
86
	discord.AddHandler(guildAddHandler)
87
	discord.AddHandler(commandHandler)
88
	discord.AddHandler(joinHandler)
89
	onStart()
90
	<-sc
91
}
92
93
// Handle new users
94
func joinHandler(discord *discordgo.Session, e *discordgo.GuildMemberAdd) {
95
	if _, ok := guilds.Guilds[e.GuildID]; !ok {
96
		dbWorker.InitNewGuild(e.GuildID, conf, guilds)
97
	} else {
98
		bot.Greetings(discord, e, guilds.Guilds[e.GuildID])
99
	}
100
}
101
102
// Handle new guilds
103
func guildAddHandler(discord *discordgo.Session, e *discordgo.GuildCreate) {
104
	if _, ok := guilds.Guilds[e.ID]; !ok {
105
		dbWorker.InitNewGuild(e.ID, conf, guilds)
106
	}
107
	emb := bot.NewEmbed("").
108
		Field(conf.GetLocaleLang("bot_joined_title", guilds.Guilds[e.ID].Language), conf.GetLocaleLang("bot_joined_text", guilds.Guilds[e.ID].Language), false)
109
	_, _ = discord.ChannelMessageSendEmbed(e.OwnerID, emb.GetEmbed())
110
}
111
112
// Handle discord messages
113
func commandHandler(discord *discordgo.Session, message *discordgo.MessageCreate) {
114
	if blacklist.CheckGuild(message.GuildID) || blacklist.CheckUser(message.Author.ID) {
115
		return
116
	}
117
	messagesCounter++
118
	user := message.Author
119
	if user.ID == botId || user.Bot {
120
		return
121
	}
122
	args := strings.Split(message.Content, " ")
123
	name := strings.ToLower(args[0])
124
	command, found := CmdHandler.Get(name)
125
	if !found {
126
		return
127
	}
128
129
	var permission = true
130
	var msg string
131
	// Checking permissions
132
	perm, err := discord.State.UserChannelPermissions(botId, message.ChannelID)
133
	if err != nil {
134
		msg = fmt.Sprintf("Error whilst getting bot permissions %v\n", err)
135
		permission = false
136
	} else {
137
		if perm&discordgo.PermissionSendMessages != discordgo.PermissionSendMessages ||
138
			perm&discordgo.PermissionAttachFiles != discordgo.PermissionAttachFiles {
139
			msg = "Permissions denied"
140
			permission = false
141
		}
142
	}
143
144
	channel, err := discord.State.Channel(message.ChannelID)
145
	if err != nil {
146
		fmt.Println("Error getting channel,", err)
147
		return
148
	}
149
	guild, err := discord.State.Guild(channel.GuildID)
150
	if err != nil {
151
		fmt.Println("Error getting guild,", err)
152
		return
153
	}
154
155
	if permission {
156
		ctx := bot.NewContext(
157
			botId,
158
			discord,
159
			guild,
160
			channel,
161
			user,
162
			message,
163
			conf,
164
			CmdHandler,
165
			Sessions,
166
			youtube,
167
			botMsg,
168
			dataType,
169
			dbWorker,
170
			guilds,
171
			botCron,
172
			twitch,
173
			albUpdater,
174
			blacklist)
175
		ctx.Args = args[1:]
176
		c := *command
177
		c(*ctx)
178
	} else {
179
		dbWorker.Log("Message", guild.ID, msg)
180
		query := []byte(fmt.Sprintf("logs,server=%v module=\"%v\"", guild.ID, "message"))
181
		addr := fmt.Sprintf("%v/write?db=%v", conf.Metrics.Address, conf.Metrics.Database)
182
		r := bytes.NewReader(query)
183
		_, _ = http.Post(addr, "", r)
184
	}
185
}
186
187
// Adds bot commands
188
func registerCommands() {
189
	CmdHandler.Register("!r", cmd.RadioCommand)
190
	CmdHandler.Register("!w", cmd.WeatherCommand)
191
	CmdHandler.Register("!t", cmd.TranslateCommand)
192
	CmdHandler.Register("!n", cmd.NewsCommand)
193
	CmdHandler.Register("!c", cmd.CurrencyCommand)
194
	CmdHandler.Register("!y", cmd.YoutubeCommand)
195
	CmdHandler.Register("!v", cmd.VoiceCommand)
196
	CmdHandler.Register("!b", cmd.BotCommand)
197
	CmdHandler.Register("!play", cmd.YoutubeShortCommand)
198
	CmdHandler.Register("!d", cmd.DebugCommand)
199
	CmdHandler.Register("!p", cmd.PollCommand)
200
	CmdHandler.Register("!m", cmd.YandexmapCommand)
201
	CmdHandler.Register("!dice", cmd.DiceCommand)
202
	CmdHandler.Register("!help", cmd.HelpCommand)
203
	CmdHandler.Register("!cron", cmd.CronCommand)
204
	CmdHandler.Register("!geoip", cmd.GeoIPCommand)
205
	CmdHandler.Register("!twitch", cmd.TwitchCommand)
206
	CmdHandler.Register("!greetings", cmd.GreetingsCommand)
207
	CmdHandler.Register("!alb", cmd.AlbionCommand)
208
	CmdHandler.Register("!slap", cmd.SlapCommand)
209
	CmdHandler.Register("!fu", cmd.FUCommand)
210
}
211
212
// MetricsSender sends metrics to InfluxDB and another services
0 ignored issues
show
comment on exported function BotUpdater should be of the form "BotUpdater ..."
Loading history...
213
func BotUpdater(d *discordgo.Session) {
214
	for {
215
		go twitch.Update()
216
		go albUpdater.Update(d, dbWorker, conf)
217
		// Calculating users count
218
		usersCount := 0
219
		for _, g := range d.State.Guilds {
220
			if !blacklist.CheckGuild(g.ID) {
221
				usersCount += g.MemberCount
222
			}
223
		}
224
		// Metrics counters
225
		queryCounters := []byte(fmt.Sprintf("counters guilds=%v,messages=%v,users=%v", len(d.State.Guilds), messagesCounter, usersCount))
226
		addrCounters := fmt.Sprintf("%v/write?db=%v&u=%v&p=%v",
227
			conf.Metrics.Address, conf.Metrics.Database, conf.Metrics.User, conf.Metrics.Password)
228
		rCounters := bytes.NewReader(queryCounters)
229
		_, _ = http.Post(addrCounters, "", rCounters)
230
231
		// Bot lists
232
		if conf.DBL.Token != "" {
233
			sendDBL(conf.DBL.BotID, conf.DBL.Token, len(d.State.Guilds))
234
		}
235
		messagesCounter = 0
236
		time.Sleep(time.Minute)
237
	}
238
}
239
240
func sendDBL(botID, token string, guilds int) {
241
	timeout := time.Duration(time.Duration(1) * time.Second)
242
	client := &http.Client{
243
		Timeout: time.Duration(timeout),
244
	}
245
	query := url.Values{}
246
	query.Add("server_count", fmt.Sprintf("%v", guilds))
247
	req, _ := http.NewRequest("POST",
248
		fmt.Sprintf("https://discordbots.org/api/bots/%v/stats",
249
			botID), strings.NewReader(query.Encode()))
250
	req.Header.Add("Authorization", token)
251
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
252
	_, _ = client.Do(req)
253
}
254
255
func onStart() {
256
	queryCounters := []byte(fmt.Sprintf("starts value=1"))
257
	addrCounters := fmt.Sprintf("%v/write?db=%v&u=%v&p=%v",
258
		conf.Metrics.Address, conf.Metrics.Database, conf.Metrics.User, conf.Metrics.Password)
259
	rCounters := bytes.NewReader(queryCounters)
260
	_, _ = http.Post(addrCounters, "", rCounters)
261
}
262