FlameInTheDark /
dtbot
| 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
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
|
|||
| 213 | func BotUpdater(d *discordgo.Session) { |
||
| 214 | for { |
||
| 215 | var vregions = make(map[string]int) |
||
| 216 | go twitch.Update() |
||
| 217 | go albUpdater.Update(d, dbWorker, conf) |
||
| 218 | // Calculating users count |
||
| 219 | usersCount := 0 |
||
| 220 | for _, g := range d.State.Guilds { |
||
| 221 | vregions[g.Region] += 1 |
||
|
0 ignored issues
–
show
|
|||
| 222 | if !blacklist.CheckGuild(g.ID) { |
||
| 223 | usersCount += g.MemberCount |
||
| 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 | // Voice region metrics |
||
| 234 | for r, c := range vregions { |
||
| 235 | queryCounters := []byte(fmt.Sprintf("region_%v count=%d", r, c)) |
||
| 236 | addrCounters := fmt.Sprintf("%v/write?db=%v&u=%v&p=%v", |
||
| 237 | conf.Metrics.Address, conf.Metrics.Database, conf.Metrics.User, conf.Metrics.Password) |
||
| 238 | rCounters := bytes.NewReader(queryCounters) |
||
| 239 | _, _ = http.Post(addrCounters, "", rCounters) |
||
| 240 | } |
||
| 241 | |||
| 242 | // Bot lists |
||
| 243 | if conf.DBL.Token != "" { |
||
| 244 | sendDBL(conf.DBL.BotID, conf.DBL.Token, len(d.State.Guilds)) |
||
| 245 | } |
||
| 246 | messagesCounter = 0 |
||
| 247 | time.Sleep(time.Minute) |
||
| 248 | } |
||
| 249 | } |
||
| 250 | |||
| 251 | func sendDBL(botID, token string, guilds int) { |
||
| 252 | timeout := time.Duration(time.Duration(1) * time.Second) |
||
| 253 | client := &http.Client{ |
||
| 254 | Timeout: time.Duration(timeout), |
||
| 255 | } |
||
| 256 | query := url.Values{} |
||
| 257 | query.Add("server_count", fmt.Sprintf("%v", guilds)) |
||
| 258 | req, _ := http.NewRequest("POST", |
||
| 259 | fmt.Sprintf("https://discordbots.org/api/bots/%v/stats", |
||
| 260 | botID), strings.NewReader(query.Encode())) |
||
| 261 | req.Header.Add("Authorization", token) |
||
| 262 | req.Header.Add("Content-Type", "application/x-www-form-urlencoded") |
||
| 263 | _, _ = client.Do(req) |
||
| 264 | } |
||
| 265 | |||
| 266 | func onStart() { |
||
| 267 | queryCounters := []byte(fmt.Sprintf("starts value=1")) |
||
| 268 | addrCounters := fmt.Sprintf("%v/write?db=%v&u=%v&p=%v", |
||
| 269 | conf.Metrics.Address, conf.Metrics.Database, conf.Metrics.User, conf.Metrics.Password) |
||
| 270 | rCounters := bytes.NewReader(queryCounters) |
||
| 271 | _, _ = http.Post(addrCounters, "", rCounters) |
||
| 272 | } |
||
| 273 |