Esempio n. 1
0
// 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).")
}
Esempio n. 2
0
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)
			}
		})
	}
}
Esempio n. 3
0
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())
}