Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
kageru | d6383af189 | ||
kageru | 6393950694 | ||
kageru | 3cdb5418ff | ||
kageru | ffae758587 | ||
kageru | 943e9fcaba | ||
kageru | a99496377e | ||
kageru | c22f81d6cb | ||
kageru | a4e7ecb92e |
|
@ -1,6 +1,9 @@
|
|||
# Selphybot Changelog
|
||||
Updates are listed in reverse chronological order.
|
||||
|
||||
### 1.5 (dev)
|
||||
- added !vc to create temporary voice channels
|
||||
|
||||
### 1.4
|
||||
- a copy of each deleted message is now send via DM to the author (suggested by CommanderLook)
|
||||
- seasonal fluff
|
||||
|
|
63
command.go
63
command.go
|
@ -56,6 +56,9 @@ func registerCommand(command Command) {
|
|||
command.Trigger = strings.ToLower(command.Trigger)
|
||||
}
|
||||
command.UsersOnCooldown = mapset.NewSet()
|
||||
if command.AllowedChannels == nil {
|
||||
command.AllowedChannels = mapset.NewSet()
|
||||
}
|
||||
commands = append(commands, &command)
|
||||
}
|
||||
|
||||
|
@ -164,7 +167,9 @@ func commandAllowed(session *discordgo.Session, message *discordgo.MessageCreate
|
|||
}
|
||||
// no allowed channels = all channels are allowed.
|
||||
// DMs are whitelisted by default
|
||||
if command.AllowedChannels.Cardinality() != 0 && !command.AllowedChannels.Contains(message.ChannelID) && !isDM(session, message) {
|
||||
if command.AllowedChannels.Cardinality() != 0 &&
|
||||
!command.AllowedChannels.Contains(message.ChannelID) &&
|
||||
isDM(session, message) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
@ -199,19 +204,28 @@ func generateReply(message *discordgo.MessageCreate, command *Command) string {
|
|||
* Hence, small wrappers around the redirect function.
|
||||
*/
|
||||
func modComplain(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
redirectMessage(s, m, config.ModChannel, true)
|
||||
success := redirectMessage(s, m, config.ModChannel, true)
|
||||
dm, _ := s.UserChannelCreate(m.Author.ID)
|
||||
s.ChannelMessageSend(dm.ID, config.ComplaintReceivedMessage)
|
||||
if success {
|
||||
s.ChannelMessageSend(dm.ID, config.ComplaintReceivedMessage)
|
||||
} else {
|
||||
s.ChannelMessageSend(dm.ID, "Could not send message. Please tell kageru about this.")
|
||||
}
|
||||
}
|
||||
|
||||
func selphyComplain(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
dm_target, _ := s.UserChannelCreate("190958368301645824")
|
||||
redirectMessage(s, m, dm_target.ID, true)
|
||||
success := redirectMessage(s, m, dm_target.ID, true)
|
||||
dm, _ := s.UserChannelCreate(m.Author.ID)
|
||||
s.ChannelMessageSend(dm.ID, config.ComplaintReceivedMessage)
|
||||
if success {
|
||||
s.ChannelMessageSend(dm.ID, config.ComplaintReceivedMessage)
|
||||
} else {
|
||||
s.ChannelMessageSend(dm.ID, "Could not send message. Please tell kageru about this.")
|
||||
}
|
||||
}
|
||||
|
||||
func redirectMessage(s *discordgo.Session, m *discordgo.MessageCreate, target string, isEmbed bool) {
|
||||
func redirectMessage(s *discordgo.Session, m *discordgo.MessageCreate, target string, isEmbed bool) bool {
|
||||
var err error
|
||||
if isEmbed {
|
||||
embed := &discordgo.MessageEmbed{
|
||||
// Embed are anonymized by default for now. Fits the use case.
|
||||
|
@ -219,10 +233,15 @@ func redirectMessage(s *discordgo.Session, m *discordgo.MessageCreate, target st
|
|||
Color: 0xbb0000,
|
||||
Description: m.Content,
|
||||
}
|
||||
s.ChannelMessageSendEmbed(target, embed)
|
||||
return
|
||||
_, err = s.ChannelMessageSendEmbed(target, embed)
|
||||
} else {
|
||||
_, err = s.ChannelMessageSend(target, messageToString(m.Message))
|
||||
}
|
||||
s.ChannelMessageSend(target, messageToString(m.Message))
|
||||
if err != nil {
|
||||
log.Printf("Could not redirect message", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func echoMessage(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
|
@ -230,14 +249,36 @@ func echoMessage(s *discordgo.Session, m *discordgo.MessageCreate) {
|
|||
}
|
||||
|
||||
func giveAgeRole(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
Member, _ := s.GuildMember(config.ServerID, m.Author.ID)
|
||||
dm, _ := s.UserChannelCreate(Member.User.ID)
|
||||
Member, err := s.GuildMember(config.ServerID, m.Author.ID)
|
||||
if err != nil {
|
||||
log.Printf("User could not be retrieved for role assignment\n%s", err)
|
||||
return
|
||||
}
|
||||
dm, err := s.UserChannelCreate(Member.User.ID)
|
||||
if err != nil {
|
||||
log.Printf("Could not reply to user\n%s", err)
|
||||
return
|
||||
}
|
||||
required := mapset.NewSetWith("416184227672096780", "416184208470310922", "416184150404628480", "416184132473847810", "440996904948465664")
|
||||
for command, role := range config.RoleCommands {
|
||||
if m.Content == command {
|
||||
// Found the command that was triggered
|
||||
// This is a restriction imposed by my own wrapper,
|
||||
// but working around it is not actually necessary for performance and makes the code uglier in other places.
|
||||
for _, newRole := range config.RoleCommands {
|
||||
// check if the user has a twitch sub or any of the patreon roles
|
||||
isAllowed := false
|
||||
for _, curRole := range Member.Roles {
|
||||
if required.Contains(curRole) {
|
||||
isAllowed = true
|
||||
}
|
||||
}
|
||||
|
||||
if !isAllowed {
|
||||
s.ChannelMessageSend(dm.ID, "Du kannst dir keine Rolle zuweisen, da weder Patreon noch Twitch mit deinem Account verlinkt ist oder du Selphy auf keiner dieser Plattformen unterstützt. Bei Problemen wende dich bitte an die `!mods`.")
|
||||
log.Printf("Denied role %s to %s. User is neither patron nor sub.", roleName(s.State, newRole), userToString(m.Author))
|
||||
return
|
||||
}
|
||||
for _, curRole := range Member.Roles {
|
||||
// If the user already has one of the available roles, tell them and exit
|
||||
if newRole == curRole {
|
||||
|
|
|
@ -24,7 +24,7 @@ func onJoin(s *discordgo.Session, member *discordgo.GuildMemberAdd) {
|
|||
if err != nil {
|
||||
// if any of the preceding operations produced an error
|
||||
log.Printf("Sending welcome @mention @%s", userToString(member.User))
|
||||
s.ChannelMessageSend(config.GeneralChannel, fmt.Sprintf("Wilkommen <@%s>. Bitte aktiviere vorübergehend DMs für diesen Server und sende eine Nachricht mit !welcome an mich.", member.User.ID))
|
||||
s.ChannelMessageSend(config.GeneralChannel, fmt.Sprintf("Wilkommen <@%s>. Bitte aktiviere vorübergehend DMs für diesen Server und sende eine Nachricht mit !welcome an mich. https://cdn.discordapp.com/attachments/333450842151714816/591581555219234826/Selphy-queen.png", member.User.ID))
|
||||
}
|
||||
}
|
||||
log.Printf("User joined: %s", userToString(member.User))
|
||||
|
|
14
helpers.go
14
helpers.go
|
@ -43,8 +43,8 @@ func isDM(s *discordgo.Session, m *discordgo.MessageCreate) bool {
|
|||
}
|
||||
|
||||
func getDMChannelFromMessage(s *discordgo.Session, m *discordgo.MessageCreate) *discordgo.Channel {
|
||||
dm, _ := s.UserChannelCreate(m.Author.ID)
|
||||
return dm
|
||||
dm, _ := s.UserChannelCreate(m.Author.ID)
|
||||
return dm
|
||||
}
|
||||
|
||||
func isAdmin(u *discordgo.User) bool {
|
||||
|
@ -55,3 +55,13 @@ func isAdmin(u *discordgo.User) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getServer() (*discordgo.Guild, error) {
|
||||
server, err := state.Guild(config.ServerID)
|
||||
return server, err
|
||||
}
|
||||
|
||||
func remove(channels []*discordgo.Channel, position int) []*discordgo.Channel {
|
||||
channels[len(channels)-1], channels[position] = channels[position], channels[len(channels)-1]
|
||||
return channels[:len(channels)-1]
|
||||
}
|
||||
|
|
30
main.go
30
main.go
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/deckarep/golang-set"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
@ -11,18 +12,19 @@ import (
|
|||
|
||||
var config = readConfig()
|
||||
var commands []*Command
|
||||
var state *discordgo.State
|
||||
|
||||
func main() {
|
||||
dg, err := discordgo.New("Bot " + config.Token)
|
||||
session, err := discordgo.New("Bot " + config.Token)
|
||||
if err != nil {
|
||||
fmt.Println("error: ", err)
|
||||
return
|
||||
}
|
||||
defer dg.Close()
|
||||
defer session.Close()
|
||||
|
||||
dg.AddHandler(evaluateMessage)
|
||||
dg.AddHandler(onJoin)
|
||||
err = dg.Open()
|
||||
session.AddHandler(evaluateMessage)
|
||||
session.AddHandler(onJoin)
|
||||
err = session.Open()
|
||||
if err != nil {
|
||||
fmt.Println("No connection:\n", err)
|
||||
return
|
||||
|
@ -34,7 +36,15 @@ func main() {
|
|||
}
|
||||
defer f.Close()
|
||||
log.SetOutput(f)
|
||||
dg.UpdateStatus(0, "!help")
|
||||
session.UpdateStatus(0, "!help")
|
||||
state = discordgo.NewState()
|
||||
server, err := session.Guild(config.ServerID)
|
||||
if err != nil {
|
||||
fmt.Println("Guild incorrectly configured. Exiting...")
|
||||
return
|
||||
}
|
||||
state.GuildAdd(server)
|
||||
go checkAndDeleteUnusedChannels(session)
|
||||
addCommands()
|
||||
|
||||
fmt.Println("Bot running. selphyWoo")
|
||||
|
@ -43,6 +53,9 @@ func main() {
|
|||
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
|
||||
<-sc
|
||||
|
||||
for _, channel := range tempChannels {
|
||||
session.ChannelDelete(channel.ID)
|
||||
}
|
||||
fmt.Println("Exiting...")
|
||||
log.Println("Exiting...")
|
||||
}
|
||||
|
@ -61,7 +74,7 @@ func addCommands() {
|
|||
registerCommand(Command{Trigger: comm, Type: CommandTypeFullMatch, DMOnly: true, Function: giveAgeRole})
|
||||
}
|
||||
|
||||
// Misc commands
|
||||
// Fluff
|
||||
registerCommand(Command{Trigger: "o/", Output: "\\o", Type: CommandTypeFullMatch, Cooldown: 10})
|
||||
registerCommand(Command{Trigger: "\\o", Output: "o/", Type: CommandTypeFullMatch, Cooldown: 10})
|
||||
registerCommand(Command{Trigger: "\\o/", Output: "/o\\", Type: CommandTypeFullMatch, Cooldown: 10})
|
||||
|
@ -75,6 +88,9 @@ func addCommands() {
|
|||
registerCommand(Command{Trigger: "!welcome", OutputEmbed: getWelcomeEmbed(), Type: CommandTypeFullMatch, DMOnly: true})
|
||||
registerCommand(Command{Trigger: "!mods", Output: "Bei Fragen, Problemen und Beschwerden wende dich bitte an die Moderatoren oder schick mir eine Nachricht beginnend mit !complain, um dich anonym zu beschweren.\nAktuell anwesende Mods werden dir rechts mit dem Rang „Maid“ angezeigt.", Type: CommandTypeFullMatch})
|
||||
|
||||
// Features :Pog:
|
||||
registerCommand(Command{Trigger: "!vc ", Type: CommandTypePrefix, Function: parseVoiceChannelCommand, AllowedChannels: mapset.NewSetWith("525852491976278016")})
|
||||
|
||||
// Admin and/or debug
|
||||
registerCommand(Command{Trigger: "<@%s> <3", Output: "<@%s> <3", Type: CommandTypeFullMatch, AdminOnly: true, OutputIsReply: true, RequiresMention: true})
|
||||
registerCommand(Command{Trigger: "echo", Type: CommandTypePrefix, Function: echoMessage, AdminOnly: true})
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var tempChannels []*discordgo.Channel
|
||||
|
||||
func parseVoiceChannelCommand(session *discordgo.Session, message *discordgo.MessageCreate) {
|
||||
userLimit, err := strconv.Atoi(strings.Split(message.Content, " ")[1])
|
||||
if err != nil {
|
||||
session.ChannelMessageSend(message.ChannelID, "Error: Expected a number after !vc")
|
||||
log.Printf("Incorrect syntax for !vc, “%s” triggered by %s", message.Content, userToString(message.Author))
|
||||
return
|
||||
}
|
||||
if userLimit > 99 {
|
||||
session.ChannelMessageSend(message.ChannelID, fmt.Sprintf("Als ob %d Leute *mit dir* in einen Channel wollen.", userLimit-1))
|
||||
log.Printf("%s tried to create a channel with %d slots", userToString(message.Author), userLimit)
|
||||
return
|
||||
}
|
||||
createData := discordgo.GuildChannelCreateData{
|
||||
Name: fmt.Sprintf("%s’s Volatile Corner", message.Author.Username),
|
||||
Type: discordgo.ChannelTypeGuildVoice,
|
||||
UserLimit: userLimit,
|
||||
ParentID: "410162599762853909",
|
||||
}
|
||||
channel, err := session.GuildChannelCreateComplex(message.GuildID, createData)
|
||||
if err != nil {
|
||||
session.ChannelMessageSend(message.ChannelID, "Couldn’t create the voice channel. Please bug kageru about this.")
|
||||
log.Printf("Failed to create voice channel, %s", err)
|
||||
return
|
||||
}
|
||||
tempChannels = append(tempChannels, channel)
|
||||
err = session.GuildMemberMove(config.ServerID, message.Author.ID, channel.ID)
|
||||
if err != nil {
|
||||
log.Printf("Couldn’t move user %s: %s", userToString(message.Author), err)
|
||||
}
|
||||
session.ChannelMessageSend(message.ChannelID, "haaaai~")
|
||||
log.Printf("Created channel %s", channel.ID)
|
||||
}
|
||||
|
||||
func checkAndDeleteUnusedChannels(session *discordgo.Session) {
|
||||
for true {
|
||||
time.Sleep(30 * time.Second)
|
||||
server, err := getServer()
|
||||
if err == nil {
|
||||
for i, channel := range tempChannels {
|
||||
if channelIsEmpty(channel.ID, server.VoiceStates) {
|
||||
session.ChannelDelete(channel.ID)
|
||||
tempChannels = remove(tempChannels, i)
|
||||
log.Printf("Deleted channel %s", channel.ID)
|
||||
log.Printf("Tempchannels: %d", len(tempChannels))
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Printf("Could not retrieve voice state from API, %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func channelIsEmpty(channelID string, voiceStates []*discordgo.VoiceState) bool {
|
||||
for _, state := range voiceStates {
|
||||
if channelID == state.ChannelID {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
Loading…
Reference in New Issue
Block a user