// the below method is invoked when the Discord Websocket API transmits // a 'guildMemberAdd' event to the bot func onGuildMemberAdd(s *discordgo.Session, event *discordgo.GuildMemberAdd) { logrus.WithFields(logrus.Fields{ "guildId": event.GuildID, "joinedAt": event.JoinedAt, "userId": event.User.ID, "username": event.User.Username, }).Debug("Received guild member add event from Discord Websocket API.") guild, err := s.Guild(event.GuildID) if err != nil { logrus.WithFields(logrus.Fields{ "guildId": event.GuildID, "capturedError": err, }).Error("Could not retrieve guild object from identifier.") return } primaryChan, err := findPrimaryChannelInGuild(s, &event.GuildID) if err != nil { logrus.WithFields(logrus.Fields{ "userId": event.User.ID, "guildId": event.GuildID, "capturedError": err, }).Error("Could not determine primary channel for guild.") return } // create a private messaging channel between the bot and the new guild member privChan, err := s.UserChannelCreate(event.User.ID) if err != nil { logrus.WithFields(logrus.Fields{ "userId": event.User.ID, "capturedError": err, }).Error("Could not create channel between bot and user.") return } // send greet message to new guild member s.ChannelMessageSend(privChan.ID, "Welcome to "+guild.Name+"! We recommend setting your Pokemon GO team to grant access to team-only channels. To do so, type `!setTeam [name]` into the #"+primaryChan.Name+" text channel to set your Pokemon GO team. Available team names are: 'valor' (red), 'mystic' (blue) and 'instinct' (yellow).") }
func SBProcessCommand(s *discordgo.Session, m *discordgo.Message, info *GuildInfo, t int64, isdbguild bool, isdebug bool, err error) { // Check if this is a command. If it is, process it as a command, otherwise process it with our modules. if len(m.Content) > 1 && m.Content[0] == '!' && (len(m.Content) < 2 || m.Content[1] != '!') { // We check for > 1 here because a single character can't possibly be a valid command private := info == nil isfree := private if info != nil { _, isfree = info.config.FreeChannels[m.ChannelID] } _, isOwner := sb.Owners[SBatoi(m.Author.ID)] isSelf := m.Author.ID == sb.SelfID if !isSelf && info != nil { ignore := false ApplyFuncRange(len(info.hooks.OnCommand), func(i int) { if info.ProcessModule(m.ChannelID, info.hooks.OnCommand[i]) { ignore = ignore || info.hooks.OnCommand[i].OnCommand(info, m) } }) if ignore && !isOwner && m.Author.ID != info.Guild.OwnerID { // if true, a module wants us to ignore this command return } } args := ParseArguments(m.Content[1:]) arg := strings.ToLower(args[0]) if info == nil { info = getDefaultServer(SBatoi(m.Author.ID)) } if info == nil { gIDs := sb.db.GetUserGuilds(SBatoi(m.Author.ID)) _, independent := sb.NonServerCommands[arg] if !independent && len(gIDs) != 1 { s.ChannelMessageSend(m.ChannelID, "```Cannot determine what server you belong to! Use !defaultserver to set which server I should use when you PM me.```") return } info = sb.guilds[gIDs[0]] if info == nil { s.ChannelMessageSend(m.ChannelID, "```I haven't been loaded on that server yet!```") return } } alias, ok := info.config.Aliases[arg] if ok { nargs := ParseArguments(alias) args = append(nargs, args[1:]...) arg = strings.ToLower(args[0]) } c, ok := info.commands[arg] if ok { if isdbguild { sb.db.Audit(AUDIT_TYPE_COMMAND, m.Author, strings.Join(args, " "), SBatoi(info.Guild.ID)) } isOwner = isOwner || m.Author.ID == info.Guild.OwnerID cmdname := strings.ToLower(c.Name()) cch := info.config.Command_channels[cmdname] _, disabled := info.config.Command_disabled[cmdname] _, restricted := sb.RestrictedCommands[cmdname] if disabled && !isOwner && !isSelf { return } if restricted && !isdbguild { return } if !private && len(cch) > 0 && !isSelf { _, reverse := cch["!"] _, ok = cch[m.ChannelID] if ok == reverse { return } } if err != nil || (!isdebug && !isfree && !isSelf) { // debug channels aren't limited if info.commandlimit.check(info.config.Commandperduration, info.config.Commandmaxduration, t) { // if we've hit the saturation limit, post an error (which itself will only post if the error saturation limit hasn't been hit) info.log.Error(m.ChannelID, "You can't input more than "+strconv.Itoa(info.config.Commandperduration)+" commands every "+TimeDiff(time.Duration(info.config.Commandmaxduration)*time.Second)+"!") return } info.commandlimit.append(t) } if !isOwner && !isSelf && !info.UserHasAnyRole(m.Author.ID, info.config.Command_roles[cmdname]) { info.log.Error(m.ChannelID, "You don't have permission to run this command! Allowed Roles: "+info.GetRoles(c)) return } cmdlimit := info.config.Command_limits[cmdname] if !isfree && cmdlimit > 0 && !isSelf { lastcmd := info.command_last[m.ChannelID][cmdname] if !RateLimit(&lastcmd, cmdlimit) { info.log.Error(m.ChannelID, "You can only run that command once every "+TimeDiff(time.Duration(cmdlimit)*time.Second)+"!") return } if len(info.command_last[m.ChannelID]) == 0 { info.command_last[m.ChannelID] = make(map[string]int64) } info.command_last[m.ChannelID][cmdname] = t } result, usepm := c.Process(args[1:], m, info) if len(result) > 0 { targetchannel := m.ChannelID if usepm && !private { channel, err := s.UserChannelCreate(m.Author.ID) info.log.LogError("Error opening private channel: ", err) if err == nil { targetchannel = channel.ID if rand.Float32() < 0.01 { info.SendMessage(m.ChannelID, "Check your ~~privilege~~ Private Messages for my reply!") } else { info.SendMessage(m.ChannelID, "```Check your Private Messages for my reply!```") } } } for len(result) > 1999 { // discord has a 2000 character limit if result[0:3] == "```" { index := strings.LastIndex(result[:1996], "\n") if index < 10 { // Ensure we process at least 10 characters to prevent an infinite loop index = 1996 } info.SendMessage(targetchannel, result[:index]+"```") result = "```" + result[index:] } else { index := strings.LastIndex(result[:1999], "\n") if index < 10 { index = 1999 } info.SendMessage(targetchannel, result[:index]) result = result[index:] } } info.SendMessage(targetchannel, result) } } else { if !info.config.IgnoreInvalidCommands { info.log.Error(m.ChannelID, "Sorry, "+args[0]+" is not a valid command.\nFor a list of valid commands, type !help.") } } } else if info != nil { // If info is nil this was sent through a private message so just ignore it completely ApplyFuncRange(len(info.hooks.OnMessageCreate), func(i int) { if info.ProcessModule(m.ChannelID, info.hooks.OnMessageCreate[i]) { info.hooks.OnMessageCreate[i].OnMessageCreate(info, m) } }) } }
func voiceStateUpdateCallback(s *discordgo.Session, v *discordgo.VoiceStateUpdate) { log.Debugf("Voice bonus On voice state update: %v", v.VoiceState) // Check if it was a part if v.ChannelID == "" { return } guild, _ := s.State.Guild(v.GuildID) if guild == nil { log.WithFields(log.Fields{ "guild": v.GuildID, }).Warning("Failed to grab guild") return } member, _ := s.State.Member(v.GuildID, v.UserID) if member == nil { log.WithFields(log.Fields{ "member": member, }).Warning("Failed to grab member") return } if member.User.Bot { return } c := voicebonusCollection{ramendb.GetCollection(v.GuildID, ConfigName)} if !c.Enabled() { return } span := c.Timespan() if span == nil { log.Error("Timespan was nil for %v", guild.ID) return } log.Debugf("Timespan is: %v", span) currentTime := time.Now().UTC() year, month, day := currentTime.Date() weekday := currentTime.Weekday() nextDay := day + utils.GetDaysTillWeekday(int(weekday), span.Weekday) startDate := time.Date(year, month, nextDay, span.Hour, span.Minute, 0, 0, time.UTC) previousDate := time.Date(year, month, nextDay-7, span.Hour, span.Minute, 0, 0, time.UTC) log.Debugf("Start Date is: %v", startDate) log.Debugf("Previous Date is: %v", previousDate) lastJoinTime := time.Unix(getUserLastJoin(v.GuildID, v.UserID), 0) log.Debugf("Last join date: %v, now: %v", lastJoinTime, currentTime) if currentTime.Before(startDate) { // Check for previous week parts. Needed if timespan crosses UTC midnight if time.Since(previousDate).Hours() > float64(span.Duration) || lastJoinTime.After(previousDate) { log.Debugf("Previous time status: %v %v", time.Since(previousDate).Hours() > float64(span.Duration), lastJoinTime.After(previousDate)) return } } else if time.Since(startDate).Hours() > float64(span.Duration) || lastJoinTime.After(startDate) { log.Debugf("Current time status: %v %v", time.Since(startDate).Hours() > float64(span.Duration), lastJoinTime.After(startDate)) return } log.Debug("Giving bits for join") bits.AddBits(s, v.GuildID, v.UserID, c.Amount(), "Voice join bonus", true) username := utils.GetPreferredName(guild, v.UserID) message := fmt.Sprintf(joinMessage, username, c.Amount(), bits.GetBits(v.GuildID, v.UserID)) channel, _ := s.UserChannelCreate(v.UserID) s.ChannelMessageSend(channel.ID, message) updateUserLastJoin(v.GuildID, v.UserID, currentTime.Unix()) }