mirror of https://github.com/veonik/squircy3
parent
18b02ecb65
commit
5843fb81be
@ -0,0 +1,132 @@
|
||||
package discord
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"code.dopame.me/veonik/squircy3/event"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var ErrNotConnected = errors.New("not connected")
|
||||
|
||||
type Config struct {
|
||||
Token string `toml:"token"`
|
||||
ActivityName string `toml:"activity"`
|
||||
OwnerID string `toml:"owner"`
|
||||
|
||||
enabled bool
|
||||
}
|
||||
|
||||
type Manager struct {
|
||||
conf Config
|
||||
|
||||
ev *event.Dispatcher
|
||||
session *discordgo.Session
|
||||
|
||||
channels map[string]*discordgo.Channel
|
||||
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func NewManager(ev *event.Dispatcher) *Manager {
|
||||
return &Manager{ev: ev, channels: make(map[string]*discordgo.Channel)}
|
||||
}
|
||||
|
||||
func (m *Manager) Configure(c Config) error {
|
||||
c.enabled = len(c.Token) > 0
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.conf = c
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) Connect() error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if m.session != nil {
|
||||
return errors.New("already connected")
|
||||
}
|
||||
if !m.conf.enabled {
|
||||
return errors.New("not enabled")
|
||||
}
|
||||
s, err := discordgo.New("Bot " + m.conf.Token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.session = s
|
||||
m.session.AddHandler(m.onMessageCreate)
|
||||
m.session.Identify.Intents = discordgo.IntentsGuildMessages | discordgo.IntentGuildMessageTyping | discordgo.IntentsDirectMessages
|
||||
m.session.Identify.Presence.Game = discordgo.Activity{Name: m.conf.ActivityName}
|
||||
return m.session.Open()
|
||||
}
|
||||
|
||||
func (m *Manager) Disconnect() error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if m.session == nil {
|
||||
return ErrNotConnected
|
||||
}
|
||||
s := m.session
|
||||
m.session = nil
|
||||
return s.Close()
|
||||
}
|
||||
|
||||
func userToMap(user *discordgo.User) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"ID": user.ID,
|
||||
"Username": user.Username,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) onMessageCreate(s *discordgo.Session, e *discordgo.MessageCreate) {
|
||||
ch, err := m.getChannel(e.ChannelID)
|
||||
isDM := false
|
||||
if err != nil {
|
||||
logrus.Warnf("%s: failed to get channel for %s: %s", PluginName, e.ChannelID, err)
|
||||
} else {
|
||||
isDM = ch.Type == discordgo.ChannelTypeDM
|
||||
}
|
||||
m.ev.Emit("discord.MESSAGE", map[string]interface{}{
|
||||
"ID": e.ID,
|
||||
"Content": e.Content,
|
||||
"ChannelID": e.ChannelID,
|
||||
"GuildID": e.GuildID,
|
||||
"Author": userToMap(e.Author),
|
||||
"FromSelf": e.Author.ID == s.State.User.ID,
|
||||
"IsDM": isDM,
|
||||
})
|
||||
}
|
||||
|
||||
func (m *Manager) MessageChannel(channelID, message string) error {
|
||||
_, err := m.session.ChannelMessageSend(channelID, message)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *Manager) MessageChannelTTS(channelID, message string) error {
|
||||
_, err := m.session.ChannelMessageSendTTS(channelID, message)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *Manager) CurrentUsername() (string, error) {
|
||||
return m.session.State.User.Username, nil
|
||||
}
|
||||
|
||||
func (m *Manager) OwnerID() string {
|
||||
return m.conf.OwnerID
|
||||
}
|
||||
|
||||
func (m *Manager) getChannel(id string) (*discordgo.Channel, error) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if ch, ok := m.channels[id]; ok {
|
||||
return ch, nil
|
||||
}
|
||||
ch, err := m.session.Channel(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m.channels[id] = ch
|
||||
return ch, nil
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package discord
|
||||
|
||||
import (
|
||||
"code.dopame.me/veonik/squircy3/config"
|
||||
"code.dopame.me/veonik/squircy3/event"
|
||||
"code.dopame.me/veonik/squircy3/plugin"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const PluginName = "discord"
|
||||
|
||||
func Initialize(m *plugin.Manager) (plugin.Plugin, error) {
|
||||
ev, err := event.FromPlugins(m)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "%s: required dependency missing (event)", PluginName)
|
||||
}
|
||||
return &discordPlugin{NewManager(ev)}, nil
|
||||
}
|
||||
|
||||
type discordPlugin struct {
|
||||
manager *Manager
|
||||
}
|
||||
|
||||
func (p *discordPlugin) Configure(c config.Config) error {
|
||||
if gcv, ok := c.Self().(*Config); ok {
|
||||
return p.manager.Configure(*gcv)
|
||||
}
|
||||
cf := Config{}
|
||||
cf.Token, _ = c.String("token")
|
||||
cf.OwnerID, _ = c.String("owner")
|
||||
cf.ActivityName, _ = c.String("activity")
|
||||
return p.manager.Configure(cf)
|
||||
}
|
||||
|
||||
func (p *discordPlugin) Options() []config.SetupOption {
|
||||
return []config.SetupOption{config.WithInitValue(&Config{})}
|
||||
}
|
||||
|
||||
func (p *discordPlugin) Name() string {
|
||||
return PluginName
|
||||
}
|
||||
|
||||
// must logs the given error as a warning
|
||||
func must(what string, err error) {
|
||||
if err != nil {
|
||||
logrus.Warnf("%s: error %s: %s", PluginName, what, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *discordPlugin) HandleRuntimeInit(gr *goja.Runtime) {
|
||||
v := gr.NewObject()
|
||||
must("setting connect", v.Set("connect", p.manager.Connect))
|
||||
must("setting messageChannel", v.Set("messageChannel", p.manager.MessageChannel))
|
||||
must("setting messageChannelTTS", v.Set("messageChannelTTS", p.manager.MessageChannelTTS))
|
||||
must("setting getCurrentUsername", v.Set("getCurrentUsername", p.manager.CurrentUsername))
|
||||
must("setting getOwnerID", v.Set("getOwnerID", p.manager.OwnerID))
|
||||
if err := gr.Set("discord", v); err != nil {
|
||||
logrus.Warnf("%s: error initializing runtime: %s", PluginName, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *discordPlugin) HandleShutdown() {
|
||||
if p.manager == nil {
|
||||
logrus.Warnf("%s: shutting down uninitialized plugin", PluginName)
|
||||
return
|
||||
}
|
||||
if err := p.manager.Disconnect(); err != nil {
|
||||
if err != ErrNotConnected {
|
||||
logrus.Warnf("%s: failed to disconnect before shutting down: %s", PluginName, err)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"code.dopame.me/veonik/squircy3/plugin"
|
||||
"code.dopame.me/veonik/squircy3/plugins/discord"
|
||||
)
|
||||
|
||||
func main() {
|
||||
plugin.Main(discord.PluginName)
|
||||
}
|
||||
|
||||
func Initialize(m *plugin.Manager) (plugin.Plugin, error) {
|
||||
return discord.Initialize(m)
|
||||
}
|
Loading…
Reference in new issue