// Message receives a Message struct and sends it to appropriate channels func Message(s *discordgo.Session, m *types.Message) error { message := strings.Join(m.Payload, "\n") var channels []string var dchannels []*discordgo.Channel var err error c := config.Get() if m.Prefix != "" { message = fmt.Sprintf("%s: %s", m.Prefix, message) } if m.Channels[0] == "*" { dchannels, err = s.GuildChannels(c.Guild) if err != nil { return err } //errhandler.Handle(err) for _, chann := range dchannels { channels = append(channels, chann.ID) } } else { channels = m.Channels } log.Debugf("%s\n", len(channels)) for _, channel := range channels { s.ChannelMessageSend(channel, message) } return nil }
func sendMessage(sess *discordgo.Session, message string) { channelid := fetchPrimaryTextChannelID(sess) logInfo("SENDING MESSAGE:", message) retryOnBadGateway(func() error { _, err := sess.ChannelMessageSend(channelid, message) return err }) }
func bdLinks(s *discordgo.Session, id string) { resp, err := http.Get("https://betterdiscord.net/home/") checkErr(err) bytes, err := ioutil.ReadAll(resp.Body) checkErr(err) rx := regexp.MustCompile(`<a href="(.*.zip)`) mm := rx.FindAllStringSubmatch(string(bytes), 2) s.ChannelMessageSend(id, fmt.Sprintf("\n`OSX:` %s\n`Windows:` %s", mm[1][1], mm[0][1])) }
func onGuildCreate(s *discordgo.Session, event *discordgo.GuildCreate) { if event.Guild.Unavailable != nil { return } for _, channel := range event.Guild.Channels { if channel.ID == event.Guild.ID { s.ChannelMessageSend(channel.ID, "**AIRHORN BOT READY FOR HORNING. TYPE `!AIRHORN` WHILE IN A VOICE CHANNEL TO ACTIVATE**") return } } }
// This function will be called (due to AddHandler above) every time a new // guild is joined. func guildCreate(s *discordgo.Session, event *discordgo.GuildCreate) { if event.Guild.Unavailable != nil { return } for _, channel := range event.Guild.Channels { if channel.ID == event.Guild.ID { _, _ = s.ChannelMessageSend(channel.ID, "Airhorn is ready! Type !airhorn while in a voice channel to play a sound.") return } } }
func checkForPermissions(s *discordgo.Session, channelID string, roleID []string) bool { var ok bool if len(roleID) > 0 { _, ok = adminIds[roleID[0]] if ok == true { return ok } } s.ChannelMessageSend(channelID, fmt.Sprintf("Insuficient permissions")) return ok }
// the below method is invoked when the Discord Websocket API transmits // a 'guildCreate' event to the bot func onGuildCreate(s *discordgo.Session, event *discordgo.GuildCreate) { logrus.WithFields(logrus.Fields{ "guildId": event.ID, "guildName": event.Name, "joinedAt": event.JoinedAt, }).Debug("Received guild create event from Discord Websocket API.") // send greet message to the appropriate general/lobby channel for _, channel := range event.Guild.Channels { if channel.ID == event.Guild.ID { s.ChannelMessageSend(channel.ID, "Pokemon Discord is ready for use! Type `!setTeam [name]` to set your Pokemon GO team.") } } }
// This function will be called (due to AddHandler above) every time a new // message is created on any channel that the autenticated bot has access to. func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { // Ignore all messages created by the bot itself if m.Author.ID == BotID { return } // If the message is "ping" reply with "Pong!" if m.Content == "ping" { _, _ = s.ChannelMessageSend(m.ChannelID, "Pong!") } // If the message is "pong" reply with "Ping!" if m.Content == "pong" { _, _ = s.ChannelMessageSend(m.ChannelID, "Ping!") } }
// Handles bot operator messages, should be refactored (lmao) func handleBotControlMessages(s *discordgo.Session, m *discordgo.MessageCreate, parts []string, g *discordgo.Guild) { if scontains(parts[1], "status") { displayBotStats(m.ChannelID) } else if scontains(parts[1], "stats") { if len(m.Mentions) >= 2 { displayUserStats(m.ChannelID, utilGetMentioned(s, m).ID) } else if len(parts) >= 3 { displayUserStats(m.ChannelID, parts[2]) } else { displayServerStats(m.ChannelID, g.ID) } } else if scontains(parts[1], "bomb") && len(parts) >= 4 { airhornBomb(m.ChannelID, g, utilGetMentioned(s, m), parts[3]) } else if scontains(parts[1], "aps") { s.ChannelMessageSend(m.ChannelID, ":ok_hand: give me a sec m8") go calculateAirhornsPerSecond(m.ChannelID) } }
func handleExternalCommand(status int, command []string, pluginDir string, plugin *types.Plugin, s *discordgo.Session, m *discordgo.Message) (handled bool) { //s := conn.Get() // always send the event to messageDelete if status == globals.MATCH || status == globals.HELP { messageDelete(s, m.ChannelID, m.ID) handled = true } if status == globals.MATCH && plugin.Type == "simple" { output, err := plugins.Exec(pluginDir, plugin.Filename, command[1:]) if err == nil { s.ChannelMessageSend(m.ChannelID, string(output)) } } else if (status == globals.MATCH || status == globals.HELP) && plugin.Type == "json" { var message types.PluginMessage if status == globals.MATCH { message.Arguments = command[1:] } else if status == globals.HELP { message.Arguments = []string{} } message.User = m.Author.Username message.Channel = m.ChannelID output, err := plugins.ExecJSON(pluginDir, plugin.Filename, &message) if err == nil { handleJSONPlugin(plugin.Name, output, s) } else { log.Warning("Could not exec json plugin %s", plugin.Name) } } else if status == globals.HELP { output, err := plugins.Exec(pluginDir, plugin.Filename, []string{}) if err == nil { s.ChannelMessageSend(m.ChannelID, string(output)) } } return }
// 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).") }
// the below method is invoked when the Discord Websocket API transmits // a 'messageCreate' event to the bot func onMessageCreate(s *discordgo.Session, event *discordgo.MessageCreate) { logrus.WithFields(logrus.Fields{ "authorId": event.Author.ID, "authorUsername": event.Author.Username, "channelId": event.ChannelID, "timestamp": event.Timestamp, "content": event.Content, }).Debug("Received message create event from Discord Websocket API.") // do not take action if the author of the message is ourself if s.State.Ready.User.ID == event.Author.ID { return } // ensure the message was not received via direct message currChannel, err := s.Channel(event.ChannelID) if err != nil { logrus.WithFields(logrus.Fields{ "channelId": event.ChannelID, "capturedError": err, }).Error("Could not retrieve channel object from identifier.") return } if currChannel.IsPrivate { s.ChannelMessageSend(event.ChannelID, "Hi! I don't respond to commands sent through direct message, as I cannot tell what Discord server you are trying to set on! Please send me a message in the appropriate text channel on a Discord server to try again.") return } // convert the text to lowercase to avoid case-sensitivity issues lowerContent := strings.ToLower(event.ContentWithMentionsReplaced()) if strings.HasPrefix(lowerContent, "!setteam ") { givenTeamName := lowerContent[9:] go handleTeamSet(s, &givenTeamName, &event.Author.ID, &event.ChannelID) } }
func handleInternalCommand(status int, command []string, s *discordgo.Session, m *discordgo.Message) (handled bool) { if status == globals.MATCH || status == globals.HELP { messageDelete(s, m.ChannelID, m.ID) handled = true } if status == globals.MATCH { switch { case command[1] == "plugins": s.ChannelMessageSend(m.ChannelID, printHelp()) case command[1] == "reload": plugins.Register() s.ChannelMessageSend(m.ChannelID, "Digo Reloaded") default: s.ChannelMessageSend(m.ChannelID, printHelp()) } } else if status == globals.HELP { s.ChannelMessageSend(m.ChannelID, printHelp()) } return }
func manualUnban(s *discordgo.Session, channelID string, roleID []string, arr []string) { if checkForPermissions(s, channelID, roleID) && len(arr) == 3 && len(arr[2]) == 21 { arr[2] = arr[2][2 : len(arr[2])-1] pgDb := dbConn() tx, err := pgDb.Begin() checkErr(err) user, _ := s.User(arr[2]) name := user.Username rows, err := tx.Query( "SELECT id, guild_id, role_id FROM bans WHERE name = $1", name) checkErr(err) flag := false for rows.Next() { flag = true var id, guild_id, role_id string rows.Scan(&id, &guild_id, &role_id) if len(guild_id) != 0 { rows.Close() _, err = tx.Exec("DELETE FROM bans WHERE id = $1", id) checkErr(err) s.GuildMemberEdit(guild_id, arr[2], []string{role_id}) s.ChannelMessageSend(channelID, fmt.Sprintf("User %s has been unbanned", name)) break } } tx.Commit() pgDb.Close() if flag == false { s.ChannelMessageSend(channelID, fmt.Sprintf("User %s is not banned", name)) } } else { s.ChannelMessageSend(channelID, fmt.Sprintf("Please check the parameters")) } }
func pullFromReddit(ses *discordgo.Session) bool { pgDb := dbConn() defer func() bool { if err := recover(); err != nil { // fmt.Println("recovered from wrong pull") pgDb.Close() return false } return true }() session, _ := geddit.NewLoginSession( "", "", "gedditAgent v1", ) rows, err := pgDb.Query( `SELECT last_url FROM reddit ORDER BY time_stamp DESC LIMIT 100`) checkErr(err) var url string urlArr := make(map[string]int) for rows.Next() { rows.Scan(&url) urlArr[url] = 1 } rows.Close() subOpts := geddit.ListingOptions{ Limit: 100, } submissions, _ := session.Frontpage(geddit.HotSubmissions, subOpts) for _, s := range submissions { _, ok := urlArr[s.URL] if ok { break } tx, err := pgDb.Begin() checkErr(err) _, err = tx.Exec("INSERT INTO reddit (last_url) VALUES ($1)", s.URL) checkErr(err) tx.Commit() if strings.Contains(s.URL, "imgur") && !strings.Contains(s.URL, "/a/") && !strings.Contains(s.URL, "/gallery/") { // fmt.Println(s.URL) rx := regexp.MustCompile(`^(https?://.*?)/(.*?)(\..*)?$`) m := rx.FindStringSubmatch(s.URL) // fmt.Println(m) base := m[1] pref := m[2] ext := m[3] // fmt.Println("after m split") if len(ext) == 0 { ext = ".jpg" } animated := imgurFilext(pref) url := base + "/" + pref + ext if animated { url = base + "/" + pref + ".gif" } response, err := http.Get(url) checkErr(err) // fmt.Println(response.ContentLength) if response.ContentLength <= 8388608 { ses.ChannelMessageSend(CHANID, fmt.Sprintf("\n```%s```\n%s\n", s.Title, url)) } else { ses.ChannelMessageSend(CHANID, fmt.Sprintf( "\n```**CANNOT EMBED FILE IS TOO LARGE**\n%s```\n%s", s.Title, s.URL)) } } else { ses.ChannelMessageSend(CHANID, fmt.Sprintf("\n```%s```\n%s\n", s.Title, s.URL)) } time.Sleep(time.Second * 2) } pgDb.Close() return true }
// This function will be called (due to above assignment) every time a new // message is created on any channel that the autenticated user has access to. func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { if !m.Author.Bot { s.ChannelMessageSend(m.ChannelID, m.Content) } }
func handleTeamSet(s *discordgo.Session, givenTeamName *string, authorID *string, channelID *string) { // validate a team option was provided to the command if *givenTeamName == "" { s.ChannelMessageSend(*channelID, "A team must be provided to this command.") return } // validate the team provided matches a valid option hasTeam := false for _, team := range teams { if *givenTeamName == team { hasTeam = true } } if !hasTeam { s.ChannelMessageSend(*channelID, "The team selected ("+*givenTeamName+") does not exist. Valid options are: "+strings.Join(teams, ", ")+".") return } currChannel, err := s.Channel(*channelID) if err != nil { logrus.WithFields(logrus.Fields{ "channelId": *channelID, "capturedError": err, }).Error("Could not parse channel identifier into channel object.") s.ChannelMessageSend(*channelID, "An error occurred while setting your team. Please wait a moment and try again.") return } currGuild, err := s.Guild(currChannel.GuildID) if err != nil { logrus.WithFields(logrus.Fields{ "guildId": currChannel.GuildID, "capturedError": err, }).Error("Could not parse guild identifier into guild object.") s.ChannelMessageSend(*channelID, "An error occurred while setting your team. Please wait a moment and try again.") return } currMember, err := s.GuildMember(currGuild.ID, *authorID) if err != nil { logrus.WithFields(logrus.Fields{ "guildId": currGuild.ID, "userId": *authorID, "capturedError": err, }).Error("Could not parse guild identifier and user identifier into guild member object.") s.ChannelMessageSend(*channelID, "An error occurred while setting your team. Please wait a moment and try again.") return } // ensure they are not an existing member of a team for _, roleID := range currMember.Roles { var role *discordgo.Role for _, guildRole := range currGuild.Roles { if guildRole.ID == roleID { role = guildRole } } if role == nil { logrus.WithFields(logrus.Fields{ "roleId": roleID, }).Error("Could not retrieve role object from identifier.") s.ChannelMessageSend(*channelID, "An error occurred while setting your team. Please wait a moment and try again.") return } for _, teamName := range teams { if role.Name == "Team "+strings.Title(teamName) { logrus.WithFields(logrus.Fields{ "roleName": role.Name, "roleId": role.ID, "userId": currMember.User.ID, "userName": currMember.User.Username, "guildId": currGuild.ID, }).Warn("Attempted team switch detected.") s.ChannelMessageSend(*channelID, "You are already a member of a team and cannot switch now. Ask an administrator if you have made a mistake selecting teams.") return } } } // add the role to the user teamTitle := strings.Title(*givenTeamName) for _, role := range currGuild.Roles { if role.Name == "Team "+teamTitle { err := s.GuildMemberEdit(currGuild.ID, *authorID, append(currMember.Roles, role.ID)) if err != nil { logrus.WithFields(logrus.Fields{ "guildId": currGuild.ID, "userId": *authorID, "roleId": role.ID, "capturedError": err, }).Error("Could not add team role to user.") s.ChannelMessageSend(*channelID, "An error occurred while setting your team. Please wait a moment and try again.") return } s.ChannelMessageSend(*channelID, "You have been set to Team "+teamTitle+".") } } }
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { if m.Author.ID == s.State.User.ID { // Ignore self return } channel, _ := s.State.Channel(m.ChannelID) if channel.IsPrivate { channel.Name = "direct message" } isMentioned := isUserMentioned(s.State.User, m.Mentions) || m.MentionEveryone if shouldIgnore(m.Author) { return } text := m.ContentWithMentionsReplaced() text = strings.Replace(text, "@everyone", "", -1) // Log cleaned up message fmt.Printf("%20s %20s %20s > %s\n", channel.Name, time.Now().Format(time.Stamp), m.Author.Username, text) commandFound, reply := commands.ParseMessage(s, m, text) if commandFound { _, err := s.ChannelMessageSend(m.ChannelID, reply) if err != nil { fmt.Println("s.ChannelMessageSend >> ", err) } return } else if strings.HasPrefix(text, "!") || strings.HasPrefix(text, ".") || strings.HasPrefix(text, "bot.") { // Ignore shit meant for other bots return } if config.ChannelIsLewd(channel.GuildID, m.ChannelID) { linksFound, reply := lewd.ParseLinks(text) if linksFound { s.ChannelMessageSend(m.ChannelID, reply) return } } // Accept the legacy mention as well and trim it off from text if strings.HasPrefix(strings.ToLower(text), "lewdbot, ") { text = text[9:] isMentioned = true } if channel.IsPrivate || isMentioned { reply := brain.Reply(text) reply = regex.Lewdbot.ReplaceAllString(reply, m.Author.Username) // Log our reply fmt.Printf("%20s %20s %20s > %s\n", channel.Name, time.Now().Format(time.Stamp), s.State.User.Username, reply) s.ChannelMessageSend(m.ChannelID, reply) } else if !config.GuildIsDumb(channel.GuildID) { // Just learn brain.Learn(text, true) } }
func banUser(s *discordgo.Session, guild *discordgo.Guild, author *discordgo.Member, channelID string, arr []string) { if len(arr) == 4 && len(arr[2]) == 21 && checkForPermissions(s, channelID, author.Roles) { arr[2] = arr[2][2 : len(arr[2])-1] userRole := "" username := "" for _, member := range guild.Members { if arr[2] == member.User.ID { username = member.User.Username userRole = member.Roles[0] break } } duration, _ := (strconv.Atoi(arr[3])) pgDb := dbConn() tx, err := pgDb.Begin() checkErr(err) rows, err := tx.Query( `SELECT duration FROM bans WHERE user_id = $1`, arr[2]) checkErr(err) var ( dur int i int ) for rows.Next() { i++ rows.Scan(&dur) } rows.Close() if i == 0 { _, err = tx.Exec( `INSERT INTO bans(name, time_stamp, duration, guild_id, role_id, user_id) VALUES($1, $2, $3, $4, $5, $6)`, username, int64(time.Now().Unix()), duration*60, guild.ID, userRole, arr[2]) checkErr(err) s.GuildMemberEdit(guild.ID, arr[2], []string{roleBannedId}) for _, c := range guild.Channels { if c.Name == "AFK" { s.GuildMemberMove(guild.ID, arr[2], c.ID) break } } s.ChannelMessageSend(channelID, fmt.Sprintf( "User %s has been temporary banned for %d minute(s)", username, duration)) } else { _, err = tx.Exec( `UPDATE bans SET duration = $1 WHERE user_id = $2`, dur+duration*60, arr[2]) checkErr(err) s.ChannelMessageSend(channelID, fmt.Sprintf( "Users %s temporary ban has been extended by %d minute(s)", username, duration)) } tx.Commit() pgDb.Close() } else { s.ChannelMessageSend(channelID, fmt.Sprintf("Please check the parameters")) } }
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()) }
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 messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { var deleteMessageAuthor bool deleteMessageAuthor = true text := m.ContentWithMentionsReplaced() if m.Author.ID == s.State.User.ID { // Ignore self return } channel, _ := s.State.Channel(m.ChannelID) if channel.IsPrivate { channel.Name = "direct message" } if strings.HasPrefix(text, "!") || strings.HasPrefix(text, ".") || strings.HasPrefix(text, "bot.") { // Ignore shit meant for other bots return } isMentioned := isUserMentioned(s.State.User, m.Mentions) || m.MentionEveryone text = strings.Replace(text, "@everyone", "", -1) // Log cleaned up message fmt.Printf("%20s %20s %20s > %s\n", channel.Name, time.Now().Format(time.Stamp), m.Author.Username, text) if shouldIgnore(m.Author) { return } c := config.Get() for _, ChannelID := range c.Channels { if m.ChannelID == ChannelID { linksFound, reply := lewd.ParseLinks(text) if linksFound { content := strings.Join(lewd.ContentLinks(m.Content)[:], " ") if deleteMessageAuthor { s.ChannelMessageDelete(m.ChannelID, m.ID) } s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("%s: %s\n%s", m.Author.Username, content, reply)) return } } } // Accept the legacy mention as well and trim it off from text if strings.HasPrefix(strings.ToLower(text), "lewdbot, ") { text = text[9:] isMentioned = true } if channel.IsPrivate || isMentioned { var reply string reply = regex.Lewdbot.ReplaceAllString(reply, m.Author.Username) // Log our reply fmt.Printf("%20s %20s %20s > %s\n", channel.Name, time.Now().Format(time.Stamp), s.State.User.Username, reply) s.ChannelMessageSend(m.ChannelID, reply) } }
//discordMsgHandler is a handler function for incomming discord messages func discordMsgHandler(s *discordgo.Session, m *discordgo.MessageCreate) { botMessages++ //Split messages into arguments args := strings.Fields(m.Content) //Check if author is admin boss := m.Author.ID == discordCfg.Boss //Check if second argument is this bots name botcheck := (len(args) > 1 && strings.ToUpper(args[1]) == discordCfg.Name) //Check if message is relevant to the bot //i.e message starts with '!' followed by a word relevant := relevantRegex.MatchString(m.Content) //If message is relevant process it otherwise leave this function if relevant { botResponses++ switch strings.ToUpper(args[0]) { //!HELP [string] //Can optionally include bots name as second argument case "!HELP": if len(args) > 1 { if strings.ToUpper(args[1]) == discordCfg.Name { s.ChannelMessageSend(m.ChannelID, discordHelp) } } else { s.ChannelMessageSend(m.ChannelID, discordHelp) } //!SUB anime.id //anime.id is the id of the anime (string with length of 3 chars) case "!SUB": if len(args) >= 2 { newAnime := anime{ID: strings.ToLower(args[1])} if newAnime.Exists() { newAnime.AddSub(m.Author.ID) s.ChannelMessageSend(m.ChannelID, "Successfully subscribed to "+newAnime.Name) } else { s.ChannelMessageSend(m.ChannelID, "Invalid ID") } } //!UNSUB anime.id //anime.id is the id of the anime (string with length of 3 chars) case "!UNSUB": if len(args) >= 2 { newAnime := anime{ID: strings.ToLower(args[1])} if newAnime.Exists() { newAnime.RemoveSub(m.Author.ID) s.ChannelMessageSend(m.ChannelID, "Successfully unsubscribed from "+newAnime.Name) } else { s.ChannelMessageSend(m.ChannelID, "Invalid ID") } } //!UPTIME [string] //Can optionally include bots name as second argument case "!UPTIME": if len(args) > 1 { if strings.ToUpper(args[1]) == discordCfg.Name { s.ChannelMessageSend(m.ChannelID, "Current uptime is "+getUptime()) } } else { s.ChannelMessageSend(m.ChannelID, "Current uptime is "+getUptime()) } //!W string //Looks up weather at the the location string case "!W": if len(args) > 1 { var location string for i := 1; i < len(args); i++ { location += args[i] + " " } location = location[:len(location)-1] s.ChannelMessageSend(m.ChannelID, getWeather(location)) } //!P string //Sets the 'currently playing' state of the bot //will only work for admin of the bot case "!P": if boss { if len(args) > 1 { var game string for i := 1; i < len(args); i++ { game += args[i] + " " } game = game[:len(game)-1] discord.UpdateStatus(0, game) } else { discord.UpdateStatus(0, "") } } //!INFO [string] //Can optionally include bots name as second argument //Lists bot usage and general information case "!INFO": if len(args) > 1 { if strings.ToUpper(args[1]) == discordCfg.Name { s.ChannelMessageSend(m.ChannelID, getInfo()) } } else { s.ChannelMessageSend(m.ChannelID, getInfo()) } //!GUILDS [string] //Can optionally include bots name as second argument //Lists all the guilds this bot is a part of //will only work for admin of the bot //FIXME case "!GUILDS": if boss && (botcheck || len(args) == 1) { s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("Currently in %d guilds: %s", len(discordCfg.Guilds), strings.Join(discordCfg.Guilds, ", "))) } } } }
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { if m.Author.Bot { return } chanl, err := s.Channel(m.ChannelID) if err != nil { return } guild, _ := s.Guild(chanl.GuildID) var author *discordgo.Member if guild != nil { author, _ = s.GuildMember(guild.ID, m.Author.ID) } checkLink(s, m.Content, chanl.ID, chanl.LastMessageID) messageContents <- m if len(m.Content) > 21 && len(m.Mentions) > 0 && m.Mentions[len(m.Mentions)-1].Username == "MrDestructoid" { arr := strings.Fields(m.Content) switch arr[1] { case "BD": bdLinks(s, m.ChannelID) // case "state": // for _, i := range guild.VoiceStates { // fmt.Println(i.UserID) // } // case "bot": // var mem runtime.MemStats // runtime.ReadMemStats(&mem) // fmt.Println(mem.HeapAlloc) case "myid": s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("```\n%v\n```", m.Author.ID)) // //---------------- NO WAY TO UTILIZE ----------- // case "joinchannel": // ch := make(chan string) // fmt.Println(strings.Join(arr[2:], " ")) // if findNjoinChannel(s, guild.ID, guild.Channels, // strings.Join(arr[2:], " "), ch) { // echo(dgv, ch) // fmt.Println("opened") // } // //---------------- NO WAY TO UTILIZE ---------- case "channels": var str string = fmt.Sprintf("\n%-20s\t%-5s\tID", "Name", "Type") for _, c := range guild.Channels { str += fmt.Sprintf("\n%-20s\t%-5s\t%s", c.Name, c.Type, c.ID) } s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("```%s```", str)) case "updateroles": updateRolesToDB(s, guild.ID) case "guild": var owner string for _, i := range guild.Members { if i.User.ID == guild.OwnerID { owner = i.User.Username } } s.ChannelMessageSend(m.ChannelID, fmt.Sprintf( "```**Guild information** \nName: %s\nOwner: %s\nID: %s\nRegion: %s\nHas members: %d```", guild.Name, owner, guild.ID, guild.Region, len(guild.Members))) case "quit": if checkForPermissions(s, chanl.ID, author.Roles) { quit = true } case "ban": banUser(s, guild, author, m.ChannelID, arr) case "unban": manualUnban(s, chanl.ID, author.Roles, arr) case "bannedusers": bannedUsers(s, m) default: s.ChannelMessageSend(chanl.ID, fmt.Sprintf("No such command")) } } }
func bannedUsers(s *discordgo.Session, m *discordgo.MessageCreate) { pgDb := dbConn() rows, err := pgDb.Query("SELECT name, time_stamp, duration from bans") checkErr(err) for rows.Next() { var time_stamp, duration int64 var name string rows.Scan(&name, &time_stamp, &duration) s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("```\n%s %s\n```", name, time.Unix(time_stamp+duration, 0).Format("2006-01-02 15:04"))) } rows.Close() pgDb.Close() }