Passed
Push — master ( f97e1c...9f4816 )
by Viktor
01:36
created

main.main   B

Complexity

Conditions 5

Size

Total Lines 44
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

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