2019-05-31 00:18:41 +01:00
|
|
|
package discord
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/bwmarrin/discordgo"
|
2020-01-30 14:39:00 +03:00
|
|
|
"github.com/micro/go-micro/v2/agent/input"
|
2020-03-11 20:55:39 +03:00
|
|
|
"github.com/micro/go-micro/v2/logger"
|
2019-05-31 00:18:41 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
type discordConn struct {
|
|
|
|
master *discordInput
|
|
|
|
exit chan struct{}
|
|
|
|
recv chan *discordgo.Message
|
|
|
|
|
|
|
|
sync.Mutex
|
|
|
|
}
|
|
|
|
|
|
|
|
func newConn(master *discordInput) *discordConn {
|
|
|
|
conn := &discordConn{
|
|
|
|
master: master,
|
|
|
|
exit: make(chan struct{}),
|
|
|
|
recv: make(chan *discordgo.Message),
|
|
|
|
}
|
|
|
|
|
|
|
|
conn.master.session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
|
|
|
|
if m.Author.ID == master.botID {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
whitelisted := false
|
|
|
|
for _, ID := range conn.master.whitelist {
|
|
|
|
if m.Author.ID == ID {
|
|
|
|
whitelisted = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(master.whitelist) > 0 && !whitelisted {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var valid bool
|
|
|
|
m.Message.Content, valid = conn.master.prefixfn(m.Message.Content)
|
|
|
|
if !valid {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
conn.recv <- m.Message
|
|
|
|
})
|
|
|
|
|
|
|
|
return conn
|
|
|
|
}
|
|
|
|
|
|
|
|
func (dc *discordConn) Recv(event *input.Event) error {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-dc.exit:
|
|
|
|
return errors.New("connection closed")
|
|
|
|
case msg := <-dc.recv:
|
|
|
|
|
|
|
|
event.From = msg.ChannelID + ":" + msg.Author.ID
|
|
|
|
event.To = dc.master.botID
|
|
|
|
event.Type = input.TextEvent
|
|
|
|
event.Data = []byte(msg.Content)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-16 00:22:00 +03:00
|
|
|
func ChunkString(s string, chunkSize int) []string {
|
|
|
|
var chunks []string
|
|
|
|
runes := []rune(s)
|
|
|
|
|
|
|
|
if len(runes) == 0 {
|
|
|
|
return []string{s}
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < len(runes); i += chunkSize {
|
|
|
|
nn := i + chunkSize
|
|
|
|
if nn > len(runes) {
|
|
|
|
nn = len(runes)
|
|
|
|
}
|
|
|
|
chunks = append(chunks, string(runes[i:nn]))
|
|
|
|
}
|
|
|
|
return chunks
|
|
|
|
}
|
|
|
|
|
2019-05-31 00:18:41 +01:00
|
|
|
func (dc *discordConn) Send(e *input.Event) error {
|
|
|
|
fields := strings.Split(e.To, ":")
|
2020-06-16 00:22:00 +03:00
|
|
|
for _, chunk := range ChunkString(string(e.Data), 2000) {
|
|
|
|
_, err := dc.master.session.ChannelMessageSend(fields[0], chunk)
|
|
|
|
if err != nil {
|
|
|
|
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
|
|
|
|
logger.Error("[bot][loop][send]", err)
|
|
|
|
}
|
2020-03-11 20:55:39 +03:00
|
|
|
}
|
2019-05-31 00:18:41 +01:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (dc *discordConn) Close() error {
|
|
|
|
if err := dc.master.session.Close(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-dc.exit:
|
|
|
|
return nil
|
|
|
|
default:
|
|
|
|
close(dc.exit)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|