v3.6.0 (music commands trimmed) #36

Merged
FernandoJVideira merged 2 commits from dev into master 2026-10-23 11:19:21 +00:00
5 changed files with 10 additions and 65 deletions
Showing only changes of commit 3eb1ce5b0a - Show all commits

No files matched your search

+1 -5
View File
@@ -60,14 +60,10 @@ Anyone can use these. `/rps`, `/rpsstats` and `/rpsleaderboard` work in servers
| `/queue` | | **DJ** role | Shows the queue | | `/queue` | | **DJ** role | Shows the queue |
| `/volume` | `value`* (0 to 150) | **DJ** role | Sets the volume | | `/volume` | `value`* (0 to 150) | **DJ** role | Sets the volume |
| `/music toggle` | | Manage Server | Turns music on or off in this server | | `/music toggle` | | Manage Server | Turns music on or off in this server |
| `/music skip` | | **DJ** role | Skips the current song |
| `/music pause`, `/music resume` | | **DJ** role | Pauses or resumes |
| `/music stop` | | **DJ** role | Stops and clears the queue |
| `/music repeat` | `mode`* (off, song, queue) | **DJ** role | Repeats the song, the queue, or nothing |
| `/music remove` | `position`* (its number in `/queue`) | **DJ** role | Removes a queued song | | `/music remove` | `position`* (its number in `/queue`) | **DJ** role | Removes a queued song |
| `/music move` | `from`*, `to`* | **DJ** role | Moves a queued song | | `/music move` | `from`*, `to`* | **DJ** role | Moves a queued song |
Requires Lavalink. See [Getting started](getting-started.md#optional-music-with-lavalink). Pause, skip, repeat and stop are buttons on the now-playing message. Requires Lavalink. See [Getting started](getting-started.md#optional-music-with-lavalink).
## Meeting rooms ## Meeting rooms
+1 -1
View File
@@ -68,7 +68,7 @@ Lavalink-powered playback. Code: `internal/music`, commands in `internal/command
- `/play` takes a name or a URL, `/queue` shows the queue, `/volume` sets 0 to 150 percent. These need a role called **DJ**. - `/play` takes a name or a URL, `/queue` shows the queue, `/volume` sets 0 to 150 percent. These need a role called **DJ**.
- The now-playing message has buttons for playback and repeat. Buttons also check for the DJ role. - The now-playing message has buttons for playback and repeat. Buttons also check for the DJ role.
- `/music toggle` (Manage Server) turns music on or off in a server. `/music skip`, `pause`, `resume`, `stop`, `repeat`, `remove` and `move` control playback and the queue (DJ role). - `/music toggle` (Manage Server) turns music on or off in a server. `/music remove` and `/music move` edit the queue (DJ role).
- The queue and now-playing state are kept in the database, and playback can also be controlled by writing to the `music_commands` table. The hosted Velox dashboard uses this (see [Database](database.md)); you never need it, the commands above do the same. - The queue and now-playing state are kept in the database, and playback can also be controlled by writing to the `music_commands` table. The hosted Velox dashboard uses this (see [Database](database.md)); you never need it, the commands above do the same.
- Music needs a Lavalink server. Without `LAVALINK_HOST` the rest of the bot works and music does not. - Music needs a Lavalink server. Without `LAVALINK_HOST` the rest of the bot works and music does not.
+1 -1
View File
@@ -44,7 +44,7 @@ func fields() []*discordgo.MessageEmbedField {
col("Fun", col("Fun",
"`/ping` `/joke` `/coinflip`", "`/dice` `/rps` `/rpsstats`", "`/rpsleaderboard`"), "`/ping` `/joke` `/coinflip`", "`/dice` `/rps` `/rpsstats`", "`/rpsleaderboard`"),
col("Music (DJ role)", col("Music (DJ role)",
"`/play` `/queue` `/volume`", "`/music skip` `pause` `resume`", "`/music stop` `repeat`", "`/music remove` `move`", "`/music toggle` (Manage Server)"), "`/play` `/queue` `/volume`", "`/music remove` `move`", "`/music toggle` (Manage Server)"),
col("Sessions and time", col("Sessions and time",
"`/schedule create`", "`/schedule list`", "`/schedule reschedule`", "`/timezone set` `show`"), "`/schedule create`", "`/schedule list`", "`/schedule reschedule`", "`/timezone set` `show`"),
col("Tickets", col("Tickets",
+7 -41
View File
@@ -10,10 +10,10 @@ import (
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
) )
// The player controls. Everything a dashboard can do to the queue (skip, pause, // Queue editing. Pausing, skipping, repeating and stopping are buttons on the
// resume, stop, repeat, remove and move a track) is also a command, so a // now-playing message, so the only queue controls that need commands are
// server never needs one. They need the DJ role, like /play, /queue and // removing a song and moving one. They need the DJ role, like /play, /queue
// /volume. Turning music on or off needs Manage Server. // and /volume. Turning music on or off needs Manage Server.
func positionOption(name, desc string) *discordgo.ApplicationCommandOption { func positionOption(name, desc string) *discordgo.ApplicationCommandOption {
return &discordgo.ApplicationCommandOption{ return &discordgo.ApplicationCommandOption{
@@ -27,15 +27,6 @@ func playerOptions() []*discordgo.ApplicationCommandOption {
return &discordgo.ApplicationCommandOption{Type: discordgo.ApplicationCommandOptionSubCommand, Name: name, Description: desc, Options: o} return &discordgo.ApplicationCommandOption{Type: discordgo.ApplicationCommandOptionSubCommand, Name: name, Description: desc, Options: o}
} }
return []*discordgo.ApplicationCommandOption{ return []*discordgo.ApplicationCommandOption{
sub("skip", "Skip the current song (DJ)"),
sub("pause", "Pause playback (DJ)"),
sub("resume", "Resume playback (DJ)"),
sub("stop", "Stop playback and clear the queue (DJ)"),
sub("repeat", "Repeat the current song, the whole queue, or nothing (DJ)",
&discordgo.ApplicationCommandOption{
Type: discordgo.ApplicationCommandOptionString, Name: "mode", Description: "What repeats", Required: true,
Choices: []*discordgo.ApplicationCommandOptionChoice{{Name: "off", Value: "off"}, {Name: "song", Value: "song"}, {Name: "queue", Value: "queue"}},
}),
sub("remove", "Remove a song from the queue (DJ)", positionOption("position", "Its number in /queue")), sub("remove", "Remove a song from the queue (DJ)", positionOption("position", "Its number in /queue")),
sub("move", "Move a song to another place in the queue (DJ)", sub("move", "Move a song to another place in the queue (DJ)",
positionOption("from", "Its number in /queue"), positionOption("to", "The number it should have")), positionOption("from", "Its number in /queue"), positionOption("to", "The number it should have")),
@@ -57,44 +48,19 @@ func title(e *music.TrackEntry) string {
return strings.TrimSpace(e.Track.Info.Title) return strings.TrimSpace(e.Track.Info.Title)
} }
// handlePlayer runs a player subcommand. The caller has checked that music is // handlePlayer runs a queue subcommand. The caller has checked that music is
// on and that the member has the DJ role. // on and that the member has the DJ role. Pause, skip, repeat and stop are
// buttons on the now-playing message, so only what has no button is a command.
func handlePlayer(s *discordgo.Session, i *discordgo.InteractionCreate, sub *discordgo.ApplicationCommandInteractionDataOption) { func handlePlayer(s *discordgo.Session, i *discordgo.InteractionCreate, sub *discordgo.ApplicationCommandInteractionDataOption) {
g := i.GuildID g := i.GuildID
args := map[string]*discordgo.ApplicationCommandInteractionDataOption{} args := map[string]*discordgo.ApplicationCommandInteractionDataOption{}
for _, o := range sub.Options { for _, o := range sub.Options {
args[o.Name] = o args[o.Name] = o
} }
current, _ := music.GetQueue(g)
needsPlayer := sub.Name != "repeat" && sub.Name != "remove" && sub.Name != "move"
if needsPlayer && current == nil {
shared.RespondEphemeral(s, i, "Nothing is playing.")
return
}
var err error var err error
var msg string var msg string
switch sub.Name { switch sub.Name {
case "skip":
err, msg = music.Skip(g), "Skipped."
case "pause":
err, msg = music.Pause(g, true), "Paused. `/music resume` continues."
case "resume":
err, msg = music.Pause(g, false), "Resumed."
case "stop":
err, msg = music.Stop(g), "Stopped, and the queue is cleared."
case "repeat":
switch args["mode"].StringValue() {
case "song":
music.SetRepeat(g, true, false)
msg = "The current song repeats."
case "queue":
music.SetRepeat(g, false, true)
msg = "The whole queue repeats."
default:
music.SetRepeat(g, false, false)
msg = "Nothing repeats."
}
case "remove": case "remove":
n := int(args["position"].IntValue()) n := int(args["position"].IntValue())
e, size := queueEntry(g, n) e, size := queueEntry(g, n)
-17
View File
@@ -686,23 +686,6 @@ func ToggleRepeatQueue(guildID string) (bool, bool) {
return repeatSong, repeatQueue return repeatSong, repeatQueue
} }
// RepeatFlags reports whether the current song or the whole queue repeats.
func RepeatFlags(guildID string) (song, queue bool) { return repeatFlags(guildID) }
// SetRepeat sets the repeat mode directly. At most one of the two applies;
// asking for both repeats the song.
func SetRepeat(guildID string, song, queue bool) {
if manager == nil {
return
}
gp := getOrCreateGuildPlayer(guildID)
manager.mu.Lock()
gp.RepeatSong = song
gp.RepeatQueue = queue && !song
manager.mu.Unlock()
syncState(guildID)
}
func repeatFlags(guildID string) (bool, bool) { func repeatFlags(guildID string) (bool, bool) {
if manager == nil { if manager == nil {
return false, false return false, false