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
![]() |
|||
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("!ww", cmd.WeatherWeekCommand) |
||
192 | CmdHandler.Register("!t", cmd.TranslateCommand) |
||
193 | CmdHandler.Register("!n", cmd.NewsCommand) |
||
194 | CmdHandler.Register("!c", cmd.CurrencyCommand) |
||
195 | CmdHandler.Register("!y", cmd.YoutubeCommand) |
||
196 | CmdHandler.Register("!v", cmd.VoiceCommand) |
||
197 | CmdHandler.Register("!b", cmd.BotCommand) |
||
198 | CmdHandler.Register("!play", cmd.YoutubeShortCommand) |
||
199 | CmdHandler.Register("!d", cmd.DebugCommand) |
||
200 | CmdHandler.Register("!p", cmd.PollCommand) |
||
201 | CmdHandler.Register("!m", cmd.YandexmapCommand) |
||
202 | CmdHandler.Register("!dice", cmd.DiceCommand) |
||
203 | CmdHandler.Register("!help", cmd.HelpCommand) |
||
204 | CmdHandler.Register("!cron", cmd.CronCommand) |
||
205 | CmdHandler.Register("!geoip", cmd.GeoIPCommand) |
||
206 | CmdHandler.Register("!twitch", cmd.TwitchCommand) |
||
207 | CmdHandler.Register("!greetings", cmd.GreetingsCommand) |
||
208 | CmdHandler.Register("!alb", cmd.AlbionCommand) |
||
209 | CmdHandler.Register("!slap", cmd.SlapCommand) |
||
210 | CmdHandler.Register("!fu", cmd.FUCommand) |
||
211 | } |
||
212 | |||
213 | // MetricsSender sends metrics to InfluxDB and another services |
||
0 ignored issues
–
show
|
|||
214 | func BotUpdater(d *discordgo.Session) { |
||
215 | for { |
||
216 | var vregions = make(map[string]int) |
||
217 | go twitch.Update() |
||
218 | go albUpdater.Update(d, dbWorker, conf) |
||
219 | // Calculating users count |
||
220 | usersCount := 0 |
||
221 | for _, g := range d.State.Guilds { |
||
222 | vregions[g.Region] += 1 |
||
0 ignored issues
–
show
|
|||
223 | if !blacklist.CheckGuild(g.ID) { |
||
224 | usersCount += g.MemberCount |
||
225 | } |
||
226 | } |
||
227 | // Metrics counters |
||
228 | queryCounters := []byte(fmt.Sprintf("counters guilds=%d,messages=%d,users=%d,voices=%d", len(d.State.Guilds), messagesCounter, usersCount, Sessions.Count())) |
||
229 | addrCounters := fmt.Sprintf("%v/write?db=%v&u=%v&p=%v", |
||
230 | conf.Metrics.Address, conf.Metrics.Database, conf.Metrics.User, conf.Metrics.Password) |
||
231 | rCounters := bytes.NewReader(queryCounters) |
||
232 | _, _ = http.Post(addrCounters, "", rCounters) |
||
233 | |||
234 | // Voice region metrics |
||
235 | for r, c := range vregions { |
||
236 | queryCounters := []byte(fmt.Sprintf("region_%s count=%d", r, c)) |
||
237 | addrCounters := fmt.Sprintf("%v/write?db=%v&u=%v&p=%v", |
||
238 | conf.Metrics.Address, conf.Metrics.Database, conf.Metrics.User, conf.Metrics.Password) |
||
239 | rCounters := bytes.NewReader(queryCounters) |
||
240 | _, _ = http.Post(addrCounters, "", rCounters) |
||
241 | } |
||
242 | |||
243 | // Bot lists |
||
244 | if conf.DBL.Token != "" { |
||
245 | sendDBL(conf.DBL.BotID, conf.DBL.Token, len(d.State.Guilds)) |
||
246 | } |
||
247 | messagesCounter = 0 |
||
248 | time.Sleep(time.Minute) |
||
249 | } |
||
250 | } |
||
251 | |||
252 | func sendDBL(botID, token string, guilds int) { |
||
253 | timeout := time.Duration(time.Duration(1) * time.Second) |
||
254 | client := &http.Client{ |
||
255 | Timeout: time.Duration(timeout), |
||
256 | } |
||
257 | query := url.Values{} |
||
258 | query.Add("server_count", fmt.Sprintf("%v", guilds)) |
||
259 | req, _ := http.NewRequest("POST", |
||
260 | fmt.Sprintf("https://discordbots.org/api/bots/%v/stats", |
||
261 | botID), strings.NewReader(query.Encode())) |
||
262 | req.Header.Add("Authorization", token) |
||
263 | req.Header.Add("Content-Type", "application/x-www-form-urlencoded") |
||
264 | _, _ = client.Do(req) |
||
265 | } |
||
266 | |||
267 | func onStart() { |
||
268 | queryCounters := []byte(fmt.Sprintf("starts value=1")) |
||
269 | addrCounters := fmt.Sprintf("%v/write?db=%v&u=%v&p=%v", |
||
270 | conf.Metrics.Address, conf.Metrics.Database, conf.Metrics.User, conf.Metrics.Password) |
||
271 | rCounters := bytes.NewReader(queryCounters) |
||
272 | _, _ = http.Post(addrCounters, "", rCounters) |
||
273 | } |
||
274 |