From 0b636319b3cdf8ef324a9f89b76eb84b035dbdad Mon Sep 17 00:00:00 2001 From: Jay Date: Fri, 28 Jun 2019 09:37:37 +0000 Subject: [PATCH] add new bot code --- go.mod | 12 ++++ go.sum | 39 +++++++++++++ main.go | 37 ++++++++++++ models/models.go | 47 +++++++++++++++ pkg/config/config.go | 80 +++++++++++++++++++++++++ pkg/options/options.go | 28 +++++++++ pkg/svc/discord/discord.go | 116 +++++++++++++++++++++++++++++++++++++ pkg/svc/discord/events.go | 43 ++++++++++++++ pkg/svc/discord/parser.go | 55 ++++++++++++++++++ 9 files changed, 457 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 models/models.go create mode 100644 pkg/config/config.go create mode 100644 pkg/options/options.go create mode 100644 pkg/svc/discord/discord.go create mode 100644 pkg/svc/discord/events.go create mode 100644 pkg/svc/discord/parser.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..da7176e --- /dev/null +++ b/go.mod @@ -0,0 +1,12 @@ +module dorisbot + +go 1.12 + +require ( + git.trj.tw/golang/utils v0.0.0-20190225142552-b019626f0349 + github.com/bwmarrin/discordgo v0.19.0 + github.com/jmoiron/sqlx v1.2.0 + github.com/lib/pq v1.1.1 + google.golang.org/appengine v1.6.1 // indirect + gopkg.in/yaml.v2 v2.2.2 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..fdc25e0 --- /dev/null +++ b/go.sum @@ -0,0 +1,39 @@ +git.trj.tw/golang/utils v0.0.0-20190225142552-b019626f0349 h1:V6ifeiJ3ExnjaUylTOz37n6z5uLwm6fjKjnztbTCaQI= +git.trj.tw/golang/utils v0.0.0-20190225142552-b019626f0349/go.mod h1:yE+qbsUsijCTdwsaQRkPT1CXYk7ftMzXsCaaYx/0QI0= +github.com/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5awQiY= +github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q= +github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= +github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4= +github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c h1:+EXw7AwNOKzPFXMZ1yNjO40aWCh3PIquJB2fYlv9wcs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go new file mode 100644 index 0000000..c205078 --- /dev/null +++ b/main.go @@ -0,0 +1,37 @@ +package main + +import ( + "dorisbot/pkg/options" + "dorisbot/pkg/svc/discord" + "fmt" + "log" +) + +func init() { + options.RegOptions() +} + +func main() { + opts := options.GetOptions() + if opts.Help { + opts.ShowUsage() + return + } + + fmt.Println("Bot Svc") + cc := make(chan bool) + botToken := "NDEyNTEzNzk2OTA1NTAwNjcy.XQ-Shw.sS-Ldtu1fgCaPPNG_Bn3i0LX2wg" + + client, err := discord.NewClient(botToken) + if err != nil { + log.Fatal(err) + } + + err = client.Connect() + if err != nil { + log.Fatal(err) + } + defer client.Close() + + <-cc +} diff --git a/models/models.go b/models/models.go new file mode 100644 index 0000000..79c709a --- /dev/null +++ b/models/models.go @@ -0,0 +1,47 @@ +package models + +import ( + "dorisbot/pkg/config" + "errors" + "fmt" + + "github.com/jmoiron/sqlx" + _ "github.com/lib/pq" +) + +// Errors +var ( + ErrDBNotInit = errors.New("database not init") +) + +var x *sqlx.DB + +// NewDB - +func NewDB(conf *config.Database) (*sqlx.DB, error) { + var err error + connStr := fmt.Sprintf("dbname=%s user=%s password=%s host=%s port=%d sslmode=%s sslrootcert=%s sslcert=%s sslkey=%s", + conf.DBName, + conf.User, + conf.Pass, + conf.Host, + conf.Port, + conf.SSLMode, + conf.SSLCa, + conf.SSLCrt, + conf.SSLKey, + ) + + x, err = sqlx.Connect("postgres", connStr) + if err != nil { + return nil, err + } + return x, nil +} + +// Ping database connection +func Ping() error { + if x == nil { + return ErrDBNotInit + } + return x.Ping() +} diff --git a/pkg/config/config.go b/pkg/config/config.go new file mode 100644 index 0000000..cb9009a --- /dev/null +++ b/pkg/config/config.go @@ -0,0 +1,80 @@ +package config + +import ( + "errors" + "io/ioutil" + "os" + "path" + + "git.trj.tw/golang/utils" + "gopkg.in/yaml.v2" +) + +// Database struct +type Database struct { + DBName string `yaml:"dbname"` + Host string `yaml:"host"` + Port int `yaml:"port"` + User string `yaml:"user"` + Pass string `yaml:"pass"` + SSLCa string `yaml:"ssl_ca"` + SSLCrt string `yaml:"ssl_crt"` + SSLKey string `yaml:"ssl_key"` + SSLMode string `yaml:"ssl_mode"` +} + +// Discord struct +type Discord struct { + BotToken string `yaml:"bot_token"` +} + +// Config - +type Config struct { + Port int `yaml:"port"` + Database *Database `yaml:"database"` + Discord *Discord `yaml:"discord"` +} + +// Errors +var ( + ErrConfigFileNotFound = errors.New("config file not found") +) + +var conf *Config + +// GetConfig - +func GetConfig() *Config { return conf } + +// LoadConfig file +func LoadConfig(p ...string) (err error) { + fp := "" + if len(p) > 0 && len(p[0]) > 0 { + fp = p[0] + } else { + wd, err := os.Getwd() + if err != nil { + return err + } + fp = path.Join(wd, "config.yml") + } + + fp = utils.ParsePath(fp) + + if exists := utils.CheckExists(fp, false); !exists { + return ErrConfigFileNotFound + } + + fileData, err := ioutil.ReadFile(fp) + if err != nil { + return err + } + + conf = &Config{} + + err = yaml.Unmarshal(fileData, conf) + if err != nil { + return err + } + + return +} diff --git a/pkg/options/options.go b/pkg/options/options.go new file mode 100644 index 0000000..085216d --- /dev/null +++ b/pkg/options/options.go @@ -0,0 +1,28 @@ +package options + +import "flag" + +// Options - +type Options struct { + Help bool + Config string +} + +var opts *Options + +// GetOptions - +func GetOptions() *Options { return opts } + +// RegOptions - +func RegOptions() { + opts = &Options{} + flag.StringVar(&opts.Config, "config", "", "config file path") + flag.StringVar(&opts.Config, "f", "", "config file path (short)") + flag.BoolVar(&opts.Help, "h", false, "show usage") + flag.Parse() +} + +// ShowUsage - +func (p *Options) ShowUsage() { + flag.Usage() +} diff --git a/pkg/svc/discord/discord.go b/pkg/svc/discord/discord.go new file mode 100644 index 0000000..fc4d2cd --- /dev/null +++ b/pkg/svc/discord/discord.go @@ -0,0 +1,116 @@ +package discord + +import ( + "errors" + "fmt" + + "github.com/bwmarrin/discordgo" +) + +// DiscordClient - +type DiscordClient struct { + Session *discordgo.Session + ID string + connected bool +} + +// Errors +var ( + ErrTokenEmpty = errors.New("token is empty") + ErrGuildIDEmpty = errors.New("guild id is empty") +) + +var client *DiscordClient + +// NewClient - +func NewClient(token string) (*DiscordClient, error) { + if len(token) == 0 { + return nil, ErrTokenEmpty + } + var err error + + client = &DiscordClient{} + client.Session, err = discordgo.New(fmt.Sprintf("Bot %s", token)) + if err != nil { + return nil, err + } + // register event + client.Session.AddHandler(messageCreateEvt) + client.Session.AddHandler(guildMemberAddEvt) + client.Session.AddHandler(guildMemberRemoveEvt) + client.Session.AddHandler(rateLimitEvt) + client.Session.AddHandler(connectEvt) + client.Session.AddHandler(disconnectEvt) + + botInfo, err := client.Session.User("@me") + if err != nil { + return client, err + } + client.ID = botInfo.ID + + return client, nil +} + +// Connect to discord websocket +func (p *DiscordClient) Connect() error { + if p.connected == true { + return nil + } + return p.Session.Open() +} + +// Close discord websocket connection +func (p *DiscordClient) Close() error { + if p.connected == false { + return nil + } + return p.Session.Close() +} + +// GetGuildOwner - +func (p *DiscordClient) GetGuildOwner(guild string) (ownerID string, err error) { + if len(ownerID) == 0 { + return "", ErrGuildIDEmpty + } + guildInfo, err := p.Session.Guild(guild) + if err != nil { + return "", err + } + ownerID = guildInfo.OwnerID + return +} + +// GuildRole - +type GuildRole struct { + Name string + ID string +} + +// GetGuildRoles - +func (p *DiscordClient) GetGuildRoles(guild string) (roles []GuildRole, err error) { + if len(guild) == 0 { + return nil, ErrGuildIDEmpty + } + + roleInfos, err := p.Session.GuildRoles(guild) + if err != nil { + return + } + + roles = make([]GuildRole, 0, len(roleInfos)) + for _, role := range roleInfos { + r := GuildRole{ + ID: role.ID, + Name: role.Name, + } + roles = append(roles, r) + } + + return +} + +// SendMessage - +func (p *DiscordClient) SendMessage() error { + + return nil +} diff --git a/pkg/svc/discord/events.go b/pkg/svc/discord/events.go new file mode 100644 index 0000000..14ab981 --- /dev/null +++ b/pkg/svc/discord/events.go @@ -0,0 +1,43 @@ +package discord + +import ( + "log" + + "github.com/bwmarrin/discordgo" +) + +func messageCreateEvt(s *discordgo.Session, evt *discordgo.MessageCreate) { + guildID := evt.GuildID + channelID := evt.ChannelID + uid := evt.Author.ID + _ = channelID + _ = uid + + ginfo, err := s.GuildRoles(guildID) + // log.Println("get user info :: ", guildID, uid, evt.Author.Username) + // uinfo, err := s.GuildMember(guildID, uid) + if err != nil { + log.Println(err) + return + } + // log.Println(uinfo.Roles) + for _, it := range ginfo { + log.Println(":: role :: ", it.ID, it.Name) + } +} + +func guildMemberAddEvt(s *discordgo.Session, evt *discordgo.GuildMemberAdd) {} + +func guildMemberRemoveEvt(s *discordgo.Session, evt *discordgo.GuildMemberRemove) {} + +func rateLimitEvt(s *discordgo.Session, evt *discordgo.RateLimit) {} + +func connectEvt(s *discordgo.Session, evt *discordgo.Connect) { + log.Println(":: Connect ::") + client.connected = true +} + +func disconnectEvt(s *discordgo.Session, evt *discordgo.Disconnect) { + log.Println(":: Disconnect ::") + client.connected = false +} diff --git a/pkg/svc/discord/parser.go b/pkg/svc/discord/parser.go new file mode 100644 index 0000000..dcf1b1f --- /dev/null +++ b/pkg/svc/discord/parser.go @@ -0,0 +1,55 @@ +package discord + +import ( + "regexp" + "strings" +) + +var tagRagexp = regexp.MustCompile("<@([0-9]+)>") + +func getTagBot(msg string) bool { + ids := tagRagexp.FindAllString(msg, -1) + if len(ids) == 0 { + return false + } + + for _, id := range ids { + if id == client.ID { + return true + } + } + + return false +} + +func getCMD(str string) (cmd string, keyword bool) { + cmd = "" + keyword = false + charNumber := []rune(str)[0] + if charNumber == 33 || charNumber == 65218 { + keyword = true + if charNumber == 65218 { + cmd = str[3:] + } else { + cmd = str[1:] + } + } else { + cmd = str + } + + return +} + +func parseTextMessage(msg string) (cmd string, keyword bool, payload string) { + tagBot := getTagBot(msg) + _ = tagBot + msg = strings.TrimSpace(tagRagexp.ReplaceAllString(msg, "")) + + strs := strings.Split(msg, " ") + + cmd, keyword = getCMD(strs[0]) + + payload = strings.Join(strs[1:], " ") + + return +}