Skip to content

Commit

Permalink
Vote, handlers permissions, temp messages, attempt to fix voice disco…
Browse files Browse the repository at this point in the history
…nnect properly
  • Loading branch information
Depado committed Nov 7, 2020
1 parent d3b73ce commit 3076e72
Show file tree
Hide file tree
Showing 10 changed files with 447 additions and 225 deletions.
6 changes: 5 additions & 1 deletion bot/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type BotInstance struct {
Soundcloud *soundcloud.Client
Voice *discordgo.VoiceConnection
Player *Player
Vote *VoteHolder
}

func NewBotInstance(lc fx.Lifecycle, c *cmd.Conf, log *zerolog.Logger, sc *soundcloud.Client) *BotInstance {
Expand All @@ -45,6 +46,7 @@ func NewBotInstance(lc fx.Lifecycle, c *cmd.Conf, log *zerolog.Logger, sc *sound
Session: dg,
Voice: voice,
Player: &Player{tracks: soundcloud.Tracks{}},
Vote: &VoteHolder{Voters: make(map[string]bool)},
}
b.Session.AddHandler(b.MessageCreated)

Expand All @@ -56,7 +58,9 @@ func NewBotInstance(lc fx.Lifecycle, c *cmd.Conf, log *zerolog.Logger, sc *sound
b.Player.session.Stop() // nolint:errcheck
b.Player.session.Cleanup()
}
b.Voice.Close()
if b.Voice != nil {
b.Voice.Close()
}
b.Session.Close()
return nil
},
Expand Down
44 changes: 38 additions & 6 deletions bot/display.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import (
"github.com/Depado/soundcloud"
"github.com/bwmarrin/discordgo"
"github.com/hako/durafmt"
"github.com/rs/zerolog/log"
)

func (b *BotInstance) SendNowPlaying(t soundcloud.Track) {
b.Player.tracksM.Lock()
defer b.Player.tracksM.Unlock()

e := &discordgo.MessageEmbed{
Title: t.Title,
URL: t.PermalinkURL,
Expand All @@ -29,11 +31,14 @@ func (b *BotInstance) SendNowPlaying(t soundcloud.Track) {
{Name: "Reposts", Value: strconv.Itoa(t.RepostsCount), Inline: true},
{Name: "Duration", Value: durafmt.Parse(time.Duration(t.Duration) * time.Millisecond).LimitFirstN(2).String(), Inline: true},
},
Footer: &discordgo.MessageEmbedFooter{
Text: fmt.Sprintf("%d tracks left in queue", len(b.Player.tracks)),
},
}

_, err := b.Session.ChannelMessageSendEmbed(b.conf.Bot.Channels.Public, e)
if err != nil {
log.Err(err).Msg("unable to send embed")
b.log.Err(err).Msg("unable to send embed")
}
}

Expand Down Expand Up @@ -64,14 +69,15 @@ func (b *BotInstance) DisplayQueue(m *discordgo.MessageCreate) {
Fields: []*discordgo.MessageEmbedField{
{Name: "Tracks", Value: strconv.Itoa(len(b.Player.tracks)), Inline: true},
{Name: "Duration", Value: durafmt.Parse(time.Duration(tot) * time.Millisecond).LimitFirstN(2).String(), Inline: true},
{Name: "Requested by", Value: fmt.Sprintf("<@%s>", m.Author.ID), Inline: true},
},
Footer: &discordgo.MessageEmbedFooter{
Text: fmt.Sprintf("Tip: Add new tracks using '%s add' or '%s a'", b.conf.Bot.Prefix, b.conf.Bot.Prefix),
Text: fmt.Sprintf("Tip: Add new tracks using '%s add' or '%s next'", b.conf.Bot.Prefix, b.conf.Bot.Prefix),
},
}
_, err := b.Session.ChannelMessageSendEmbed(m.ChannelID, e)
if err != nil {
log.Err(err).Msg("unable to send embed")
b.log.Err(err).Msg("unable to send embed")
}
}

Expand All @@ -92,7 +98,13 @@ func (b *BotInstance) SendNotice(title, body, footer string, channel string) {
}
_, err := b.Session.ChannelMessageSendEmbed(channel, e)
if err != nil {
log.Err(err).Msg("unable to send embed")
b.log.Err(err).Msg("unable to send embed")
}
}

func (b *BotInstance) DeleteUserMessage(m *discordgo.MessageCreate) {
if err := b.Session.ChannelMessageDelete(m.ChannelID, m.ID); err != nil {
b.log.Err(err).Msg("unable to delete user message")
}
}

Expand All @@ -108,6 +120,26 @@ func (b *BotInstance) SendNamedNotice(m *discordgo.MessageCreate, prefix, title,
}
_, err := b.Session.ChannelMessageSendEmbed(m.ChannelID, e)
if err != nil {
log.Err(err).Msg("unable to send embed")
b.log.Err(err).Msg("unable to send embed")
}
}

func (b *BotInstance) DisplayTemporaryMessage(m *discordgo.MessageCreate, title, body, footer string) {
e := &discordgo.MessageEmbed{
Title: title,
Description: body,
Footer: &discordgo.MessageEmbedFooter{Text: footer},
Color: 0xff5500,
}
mess, err := b.Session.ChannelMessageSendEmbed(m.ChannelID, e)
if err != nil {
b.log.Err(err).Msg("unable to send embed")
}

go func(mess *discordgo.Message) {
time.Sleep(5 * time.Second)
if err := b.Session.ChannelMessageDelete(mess.ChannelID, mess.ID); err != nil {
b.log.Err(err).Msg("unable to delete message")
}
}(mess)
}
8 changes: 0 additions & 8 deletions bot/documentation.go

This file was deleted.

123 changes: 123 additions & 0 deletions bot/handlers_control.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package bot

import (
"github.com/bwmarrin/discordgo"
)

func (b *BotInstance) PlayHandler(m *discordgo.MessageCreate) {
b.PlayQueue()
b.SendNamedNotice(m, "Requested by", "⏯️ Play", "", "")
b.DeleteUserMessage(m)
}

func (b *BotInstance) PauseHandler(m *discordgo.MessageCreate) {
defer b.DeleteUserMessage(m)
if !b.Player.playing {
b.SendNamedNotice(m, "Requested by", "⏯️ Pause", "Nothing to do", "")
return
}

if !b.Player.pause {
b.Player.stream.SetPaused(true)
b.Player.pause = true
b.SendNamedNotice(m, "Requested by", "⏯️ Pause", "", "")
} else {
b.SendNamedNotice(m, "Requested by", "⏯️ Pause", "Nothing to do", "")
}
}

func (b *BotInstance) ResumeHandler(m *discordgo.MessageCreate) {
defer b.DeleteUserMessage(m)
if !b.Player.playing {
b.SendNamedNotice(m, "Requested by", "⏯️ Resume", "Nothing to do", "")
return
}
if b.Player.pause {
b.Player.stream.SetPaused(false)
b.Player.pause = false
b.SendNamedNotice(m, "Requested by", "⏯️ Resume", "", "")
} else {
b.SendNamedNotice(m, "Requested by", "⏯️ Resume", "Nothing to do", "")
}
}

func (b *BotInstance) StopHandler(m *discordgo.MessageCreate) {
defer b.DeleteUserMessage(m)
if !b.restricted(m) {
b.DisplayTemporaryMessage(m, "", "You do not have permission to stop the player", "")
return
}
if !b.Player.playing {
b.SendNamedNotice(m, "Requested by", "⏹️ Stop", "Nothing to do", "")
return
}
b.Player.session.Stop() // nolint:errcheck
b.Player.stop = true
b.SendNamedNotice(m, "Requested by", "⏹️ Stop", "", "")
}

func (b *BotInstance) SkipHandler(m *discordgo.MessageCreate) {
defer b.DeleteUserMessage(m)
if !b.restricted(m) {
b.DisplayTemporaryMessage(m, "", "You do not have permission to arbitrarily skip a track", "Tip: Start a vote using '!fox vote'")
return
}

if b.Player.playing {
b.Player.session.Stop() // nolint:errcheck
b.SendNamedNotice(m, "Requested by", "⏭️ Skip", "The currently playing track has been skipped", "Note: This can take a few seconds")
if err := b.Session.ChannelMessageDelete(m.ChannelID, m.ID); err != nil {
b.log.Err(err).Msg("unable to delete user message")
}
} else {
b.Player.Pop()
b.SendNamedNotice(m, "Requested by", "⏭️ Skip", "The next track in queue has been skipped", "")
if err := b.Session.ChannelMessageDelete(m.ChannelID, m.ID); err != nil {
b.log.Err(err).Msg("unable to delete user message")
}
}
}

func (b *BotInstance) JoinHandler(m *discordgo.MessageCreate) {
defer b.DeleteUserMessage(m)
if !b.restricted(m) {
b.DisplayTemporaryMessage(m, "", "Permission denied", "Tip: Only admins and DJs can do that")
return
}

b.log.Debug().Str("user", m.Author.Username).Str("method", "join").Msg("called")
if b.Voice == nil {
voice, err := b.Session.ChannelVoiceJoin(b.conf.Bot.Guild, b.conf.Bot.Channels.Voice, false, true)
if err != nil {
b.SendNamedNotice(m, "Requested by", "Unable to join voice channel", "", "Error was: "+err.Error())
b.log.Error().Err(err).Msg("unable to connect to voice channel")
return
}
b.Voice = voice
b.log.Debug().Str("user", m.Author.Username).Str("method", "join").Msg("bot joined vocal channel")
}
}

func (b *BotInstance) LeaveHandler(m *discordgo.MessageCreate) {
defer b.DeleteUserMessage(m)
if !b.restricted(m) {
b.DisplayTemporaryMessage(m, "", "Permission denied", "Tip: Only admins and DJs can do that")
return
}

b.log.Debug().Str("user", m.Author.Username).Str("method", "leave").Msg("called")
if b.Voice != nil {
if b.Player.playing {
b.Player.session.Stop() // nolint:errcheck
b.Player.stop = true
}
if err := b.Voice.Disconnect(); err != nil {
b.SendNamedNotice(m, "Requested by", "Unable to leave voice channel", "", "Error was: "+err.Error())
b.log.Error().Err(err).Msg("unable to disconnect from voice channel")
return
}
b.Voice = nil
b.log.Debug().Str("user", m.Author.Username).Str("method", "leave").Msg("bot left vocal channel")
return
}
}
104 changes: 104 additions & 0 deletions bot/handlers_public.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package bot

import (
"fmt"
"strings"

"github.com/bwmarrin/discordgo"
"github.com/rs/zerolog/log"
)

// AddHandler is in charge of pushing a track or playlist to the end of the
// current queue
func (b *BotInstance) AddHandler(m *discordgo.MessageCreate, args []string) {
if len(args) < 1 {
b.SendNotice("", fmt.Sprintf("Usage: `%s <add|a> <soundcloud URL>`", b.conf.Bot.Prefix), "", m.ChannelID)
return
}

url := args[0]
url = strings.Trim(url, "<>")
if !strings.HasPrefix(url, "https://soundcloud.com") {
b.SendNotice("", "This doesn't look like a SoundCloud URL", "", m.ChannelID)
return
}

b.AddToQueue(m, url, false)
if err := b.Session.ChannelMessageDelete(m.ChannelID, m.ID); err != nil {
b.log.Err(err).Msg("unable to delete user message")
}
}

// NextHandler is in charge of pushing a track or playlist in front of the rest
// of the queue
func (b *BotInstance) NextHandler(m *discordgo.MessageCreate, args []string) {
if len(args) < 1 {
b.SendNotice("", fmt.Sprintf("Usage: `%s <next|n> <soundcloud URL>`", b.conf.Bot.Prefix), "", m.ChannelID)
return
}

url := args[0]
url = strings.Trim(url, "<>")
if !strings.HasPrefix(url, "https://soundcloud.com") {
b.SendNotice("", "This doesn't look like a SoundCloud URL", "", m.ChannelID)
return
}

b.AddToQueue(m, url, true)
if err := b.Session.ChannelMessageDelete(m.ChannelID, m.ID); err != nil {
b.log.Err(err).Msg("unable to delete user message")
}
}

// HelpHandler will handle incoming requests for help
func (b *BotInstance) HelpHandler(m *discordgo.MessageCreate) {
var doc = &discordgo.MessageEmbed{
Title: "Fox Help",
Color: 0xff5500,
Fields: []*discordgo.MessageEmbedField{
{Name: "Help", Value: fmt.Sprintf("%s <help|h>", b.conf.Bot.Prefix), Inline: true},
{Name: "Add tracks", Value: fmt.Sprintf("%s <add|a> <soundcloud url>", b.conf.Bot.Prefix), Inline: true},
{Name: "Add next tracks", Value: fmt.Sprintf("%s <next|n> <soundcloud url>", b.conf.Bot.Prefix)},
{Name: "Channel", Value: fmt.Sprintf("%s <join/leave>", b.conf.Bot.Prefix)},
{Name: "Display Queue", Value: fmt.Sprintf("%s <queue|q>", b.conf.Bot.Prefix), Inline: true},
{Name: "Shuffle Queue", Value: fmt.Sprintf("%s <queue|q> shuffle", b.conf.Bot.Prefix), Inline: true},
{Name: "Clear Queue", Value: fmt.Sprintf("%s <queue|q> clear", b.conf.Bot.Prefix), Inline: true},
{Name: "Control", Value: fmt.Sprintf("%s <play/pause/resume/stop>", b.conf.Bot.Prefix)},
},
}
_, err := b.Session.ChannelMessageSendEmbed(m.ChannelID, doc)
if err != nil {
log.Err(err).Msg("unable to send embed")
}
if err := b.Session.ChannelMessageDelete(m.ChannelID, m.ID); err != nil {
b.log.Err(err).Msg("unable to delete user message")
}
}

// QueueHandler is in charge of dealing with queue commands such as displaying
// the current queue, shuffling the queue or in the control channel, clearing it
func (b *BotInstance) QueueHandler(m *discordgo.MessageCreate, args []string) {
if len(args) == 0 {
b.DisplayQueue(m)
if err := b.Session.ChannelMessageDelete(m.ChannelID, m.ID); err != nil {
b.log.Err(err).Msg("unable to delete user message")
}
return
}
switch args[0] {
case "shuffle":
b.Player.Shuffle()
b.SendNamedNotice(m, "Requested by", "🎲 Shuffle!", fmt.Sprintf("I shuffled %d tracks for you.", len(b.Player.tracks)), "")
if err := b.Session.ChannelMessageDelete(m.ChannelID, m.ID); err != nil {
b.log.Err(err).Msg("unable to delete user message")
}
case "clear": // The clear command is not public and shouldn't be used
if b.restricted(m) {
b.Player.Clear()
b.SendNamedNotice(m, "Requested by", "🚮 Clear", "The queue has been reset", "")
if err := b.Session.ChannelMessageDelete(m.ChannelID, m.ID); err != nil {
b.log.Err(err).Msg("unable to delete user message")
}
}
}
}
Loading

0 comments on commit 3076e72

Please sign in to comment.