2018-05-17 16:30:29 +02:00
package main
import (
"fmt"
"encoding/json"
2018-06-01 21:42:06 +02:00
"strings"
2018-05-17 16:30:29 +02:00
"os"
"os/signal"
"syscall"
2018-05-25 17:21:17 +02:00
"regexp"
2018-05-26 12:51:05 +02:00
"log"
2018-05-17 16:30:29 +02:00
"github.com/bwmarrin/discordgo"
)
2018-05-26 04:23:10 +02:00
type Embed struct {
Message string
QuestionsTitle string
QuestionsText string
BugsTitle string
BugsText string
Image string
}
2018-05-17 16:30:29 +02:00
type Config struct {
2018-05-26 04:23:10 +02:00
AdminID string
ServerID string
LockedRoleID string
2018-05-17 16:30:29 +02:00
Token string
WelcomeChannel string
2018-06-02 14:03:16 +02:00
GeneralChannel string
2018-06-01 11:59:28 +02:00
SendWelcomeDM bool
RequireAccept bool
2018-06-01 21:42:06 +02:00
ComplaintReceivedMessage string
ModChannel string
2018-05-26 04:23:10 +02:00
WelcomeEmbed Embed
2018-06-01 11:59:28 +02:00
RoleCommands map [ string ] string
2018-05-17 16:30:29 +02:00
}
var config = readConfig ( )
func readConfig ( ) Config {
2018-06-02 13:17:46 +02:00
file , _ := os . Open ( "config.json" )
2018-05-17 16:30:29 +02:00
conf := Config { }
_ = json . NewDecoder ( file ) . Decode ( & conf )
file . Close ( )
return conf
}
func main ( ) {
dg , err := discordgo . New ( "Bot " + config . Token )
if err != nil {
fmt . Println ( "error: " , err )
return
}
dg . AddHandler ( genericReply )
dg . AddHandler ( onJoin )
err = dg . Open ( )
if err != nil {
fmt . Println ( "no connection, " , err )
return
}
2018-05-26 12:51:05 +02:00
f , err := os . OpenFile ( "selphybot.log" , os . O_RDWR | os . O_CREATE | os . O_APPEND , 0666 )
if err != nil {
fmt . Println ( "error opening log file: %v" , err )
}
defer f . Close ( )
log . SetOutput ( f )
2018-05-17 16:30:29 +02:00
fmt . Println ( "bot running. selphyWoo" )
sc := make ( chan os . Signal , 1 )
signal . Notify ( sc , syscall . SIGINT , syscall . SIGTERM , os . Interrupt , os . Kill )
<- sc
dg . Close ( )
}
2018-06-01 22:32:28 +02:00
func getWelcomeEmbed ( ) * discordgo . MessageEmbed {
return & discordgo . MessageEmbed {
Author : & discordgo . MessageEmbedAuthor { } ,
Color : 0xffb90f ,
Description : config . WelcomeEmbed . Message ,
Fields : [ ] * discordgo . MessageEmbedField {
& discordgo . MessageEmbedField {
Name : config . WelcomeEmbed . QuestionsTitle ,
Value : config . WelcomeEmbed . QuestionsText ,
Inline : true ,
} ,
& discordgo . MessageEmbedField {
Name : config . WelcomeEmbed . BugsTitle ,
Value : fmt . Sprintf ( config . WelcomeEmbed . BugsText , config . AdminID ) ,
Inline : true ,
} ,
} ,
Thumbnail : & discordgo . MessageEmbedThumbnail {
URL : config . WelcomeEmbed . Image ,
} ,
}
}
2018-05-26 04:23:10 +02:00
func onJoin ( s * discordgo . Session , member * discordgo . GuildMemberAdd ) {
2018-06-01 11:59:28 +02:00
if ! member . User . Bot && config . RequireAccept {
2018-05-26 04:23:10 +02:00
s . GuildMemberRoleAdd ( config . ServerID , member . User . ID , config . LockedRoleID )
}
2018-06-01 11:59:28 +02:00
if ! member . User . Bot && config . SendWelcomeDM {
dm , err := s . UserChannelCreate ( member . User . ID )
if err != nil {
2018-06-02 14:03:16 +02:00
log . Println ( fmt . Sprintf ( "Error creating DM with %s" , userToString ( member . User ) , err ) )
2018-06-01 11:59:28 +02:00
} else {
2018-06-01 22:32:28 +02:00
embed := getWelcomeEmbed ( )
2018-06-02 14:03:16 +02:00
_ , err = s . ChannelMessageSendEmbed ( dm . ID , embed )
if err != nil {
log . Println ( fmt . Sprintf ( "Error sending DM to %s" , userToString ( member . User ) , err ) )
}
}
if err != nil {
// if any of the preceding operations produced an error
log . Printf ( "Sending welcome @mention at %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 ) )
2018-06-01 11:59:28 +02:00
}
}
2018-05-26 12:51:05 +02:00
log . Printf ( "User joined: %s" , userToString ( member . User ) )
2018-05-26 04:23:10 +02:00
}
func unlockUser ( s * discordgo . Session , id string ) {
s . GuildMemberRoleRemove ( config . ServerID , id , config . LockedRoleID )
2018-05-26 12:51:05 +02:00
log . Printf ( "Removed lock from user: %s" , userToString ( getUser ( s , id ) ) )
}
func userToString ( u * discordgo . User ) string {
return fmt . Sprintf ( "%s#%s (ID: %s)" , u . Username , u . Discriminator , u . ID )
}
2018-06-01 11:59:28 +02:00
func roleName ( s * discordgo . State , rid string ) string {
role , _ := s . Role ( config . ServerID , rid )
return role . Name
}
2018-05-26 12:51:05 +02:00
func channelToString ( c * discordgo . Channel ) string {
return fmt . Sprintf ( "%s (ID: %s) on %s" , c . Name , c . ID , c . GuildID )
}
func messageToString ( m * discordgo . Message ) string {
return fmt . Sprintf ( "<%s#%s>: %s" , m . Author . Username , m . Author . Discriminator , m . Content )
}
func getChannel ( s * discordgo . State , cid string ) * discordgo . Channel {
channel , _ := s . Channel ( cid )
return channel
}
func getUser ( s * discordgo . Session , uid string ) * discordgo . User {
user , _ := s . User ( uid )
return user
2018-05-26 04:23:10 +02:00
}
2018-05-26 12:51:05 +02:00
/ * func undelete ( s * discordgo . Session , m * discordgo . MessageDelete ) {
channel , _ := s . State . Channel ( m . ChannelID )
message , _ := s . State . Message ( m . ChannelID , m . ID )
log . Println ( fmt . Sprintf ( "Someone deleted a message in %s: “%s”" , channel . Name , messageToString ( message ) ) )
} * /
2018-06-01 21:42:06 +02:00
func redirectComplaint ( s * discordgo . Session , m * discordgo . MessageCreate ) {
embed := & discordgo . MessageEmbed {
Author : & discordgo . MessageEmbedAuthor { } ,
Color : 0xbb0000 ,
Description : m . Content ,
2018-05-17 16:30:29 +02:00
}
2018-06-01 21:42:06 +02:00
s . ChannelMessageSendEmbed ( config . ModChannel , embed )
}
2018-05-17 16:30:29 +02:00
2018-06-01 21:42:06 +02:00
func receivedDM ( s * discordgo . Session , m * discordgo . MessageCreate ) {
log . Printf ( "Received DM from %s with content: “%s”" , userToString ( m . Author ) , m . Content )
fmt . Sprintf ( "Received DM from %s with content: “%s”" , userToString ( m . Author ) , m . Content )
Member , _ := s . GuildMember ( config . ServerID , m . Author . ID )
dm , _ := s . UserChannelCreate ( Member . User . ID )
2018-06-01 22:32:28 +02:00
if m . Content == "!welcome" {
s . ChannelMessageSendEmbed ( dm . ID , getWelcomeEmbed ( ) )
return
}
2018-06-01 21:42:06 +02:00
if strings . HasPrefix ( m . Content , "!complain" ) {
redirectComplaint ( s , m )
s . ChannelMessageSend ( dm . ID , config . ComplaintReceivedMessage )
return
}
for comm , role := range config . RoleCommands {
if m . Content == comm {
for _ , irole := range config . RoleCommands {
for _ , mrole := range Member . Roles {
if irole == mrole {
s . ChannelMessageSend ( dm . ID , "Baka, du kannst nur eine der Rollen haben." )
log . Printf ( "Denied Role %s to %s. User already has %s" , roleName ( s . State , irole ) , userToString ( m . Author ) , roleName ( s . State , irole ) )
return
2018-06-01 11:59:28 +02:00
}
}
}
2018-06-01 21:42:06 +02:00
log . Printf ( "Giving Role %s to %s" , roleName ( s . State , role ) , userToString ( m . Author ) )
s . ChannelMessageSend ( dm . ID , "Haaai, Ryoukai desu~" )
s . GuildMemberRoleAdd ( config . ServerID , m . Author . ID , role )
2018-06-01 11:59:28 +02:00
}
}
2018-06-01 21:42:06 +02:00
}
func genericReply ( s * discordgo . Session , m * discordgo . MessageCreate ) {
if m . Author . ID == s . State . User . ID {
log . Printf ( "<Self> %s" , m . Content )
return
}
if getChannel ( s . State , m . ChannelID ) . Type == discordgo . ChannelTypeDM {
receivedDM ( s , m )
}
2018-05-26 04:23:10 +02:00
if m . Author . ID == config . AdminID {
replyGodmode ( s , m )
} else if m . ChannelID == config . WelcomeChannel {
s . ChannelMessageDelete ( m . ChannelID , m . ID )
if m . Content == "!accept" {
unlockUser ( s , m . Author . ID )
}
return
}
// In case this doesn’t work with your font: the last character is a winking emoji.
winks , _ := regexp . MatchString ( "([()|DoO];|;[()|DoOpP]|:wink:|😉)" , m . Content )
2018-05-25 17:21:17 +02:00
if winks {
2018-06-01 11:59:28 +02:00
s . ChannelMessageSend ( m . ChannelID , fmt . Sprintf ( "<@%s> Oboe!" , m . Author . ID ) )
2018-05-25 17:21:17 +02:00
s . ChannelMessageDelete ( m . ChannelID , m . ID )
2018-05-26 12:51:05 +02:00
channel := getChannel ( s . State , m . ChannelID )
log . Printf ( "Deleted message by %s in %s. Content: “%s”" , userToString ( m . Author ) , channelToString ( channel ) , m . Content )
2018-05-17 16:30:29 +02:00
return
}
// As per our majesty’s command:
if m . Content == "\\o" {
s . ChannelMessageSend ( m . ChannelID , "o/" )
2018-05-26 12:51:05 +02:00
log . Printf ( "o/ at %s" , userToString ( m . Author ) )
2018-05-17 16:30:29 +02:00
} else if m . Content == "o/" {
s . ChannelMessageSend ( m . ChannelID , "\\o" )
2018-05-26 12:51:05 +02:00
log . Printf ( "\\o at %s" , userToString ( m . Author ) )
2018-06-01 11:59:28 +02:00
} else if m . Content == "ayy" {
s . ChannelMessageSend ( m . ChannelID , "lmao" )
log . Printf ( "ayy lmao at %s" , userToString ( m . Author ) )
2018-05-17 16:30:29 +02:00
}
}
2018-05-26 04:23:10 +02:00
// Admin stuff down here. This is very server-specific
func replyGodmode ( s * discordgo . Session , m * discordgo . MessageCreate ) {
2018-06-01 21:42:06 +02:00
if m . Content == fmt . Sprintf ( "<@%s> <3" , s . State . User . ID ) {
s . ChannelMessageSend ( m . ChannelID , fmt . Sprintf ( "<@%s> <3" , config . AdminID ) )
}
2018-06-01 11:59:28 +02:00
/ *
2018-05-26 04:23:10 +02:00
if m . Content == "print_rules()" {
2018-05-26 12:51:05 +02:00
channel := getChannel ( s . State , m . ChannelID )
log . Printf ( "print_rules() triggered by %s in %s." , userToString ( m . Author ) , channelToString ( channel ) )
2018-05-26 04:23:10 +02:00
embedColor := 0xffb90f // kageru gold
embed := & discordgo . MessageEmbed {
Author : & discordgo . MessageEmbedAuthor { } ,
Color : embedColor ,
Description : config . WelcomeEmbed . Message ,
Fields : [ ] * discordgo . MessageEmbedField {
& discordgo . MessageEmbedField {
Name : config . WelcomeEmbed . QuestionsTitle ,
Value : config . WelcomeEmbed . QuestionsText ,
Inline : true ,
} ,
& discordgo . MessageEmbedField {
Name : config . WelcomeEmbed . BugsTitle ,
Value : fmt . Sprintf ( config . WelcomeEmbed . BugsText , config . AdminID ) ,
Inline : true ,
} ,
} ,
Thumbnail : & discordgo . MessageEmbedThumbnail {
URL : config . WelcomeEmbed . Image ,
} ,
}
s . ChannelMessageSendEmbed ( m . ChannelID , embed )
embed = & discordgo . MessageEmbed {
Author : & discordgo . MessageEmbedAuthor { } ,
Color : embedColor ,
Fields : [ ] * discordgo . MessageEmbedField {
& discordgo . MessageEmbedField {
Name : config . WelcomeEmbed . RulesTitle ,
Value : config . WelcomeEmbed . RulesText ,
Inline : true ,
} ,
} ,
}
s . ChannelMessageSendEmbed ( m . ChannelID , embed )
embed = & discordgo . MessageEmbed {
Author : & discordgo . MessageEmbedAuthor { } ,
Color : embedColor ,
Fields : [ ] * discordgo . MessageEmbedField {
& discordgo . MessageEmbedField {
Name : config . WelcomeEmbed . RulesTitle ,
Value : config . WelcomeEmbed . RulesText2 ,
Inline : true ,
} ,
} ,
}
s . ChannelMessageSendEmbed ( m . ChannelID , embed )
2018-05-17 16:30:29 +02:00
}
2018-06-01 11:59:28 +02:00
* /
2018-05-17 16:30:29 +02:00
}