Skip to content

Commit

Permalink
Add seek command (supersedes #344) (#674)
Browse files Browse the repository at this point in the history
* Add seek command

* Combine nested if statements

* Put the seek command in correct place to keep alphabetical order

* Add license header

* Brackets on next line

* Restructure if-statements

* Check for permissions with DJCommand#checkDJPermission

* Make regex slightly smaller

* Optimize imports

* Output length of current track if requested seek time is invalid

* Restate seeked point when seeked successfully

* Add empty newline at end of file to keep consistency

* Create TimeUtil class for parsing and formatting time

* Move FormatUtil#formatTime to TimeUtil, and refactor

* Apply requested changes (Pass 2)

* Seek based on current position in track

* Apply requested changes (Pass 3)

* Add javadoc param

* Apply requested changes (Pass 4)

* Fix merge

* Avoid reassigning parameter (Codacy)

* Rework timestamp parsing

* Refactor timestamp parsing

* Apply requested changes (Pass 5)

* Add examples in help

* Apply requested changes (Pass 6)

* Fix missing import

* Keep track of start timestamp & add "unit" times

* Fix my abdominal merge with QueuedTrack

* Use RequestMetadata to store start timestamp

* Store request info in request metadata

* Add regex to try getting a timestamp from the url

* Require RequestMetadata for QueuedTracks

* Add some unit tests for unit seeking

* Add docs & examples

---------

Co-authored-by: Whew., Inc <22574706+Whew-Inc@users.noreply.github.com>
  • Loading branch information
MichailiK and whew-inc committed May 10, 2024
1 parent b3ffbdb commit 81322ef
Show file tree
Hide file tree
Showing 13 changed files with 432 additions and 53 deletions.
4 changes: 2 additions & 2 deletions src/main/java/com/jagrosh/jmusicbot/BotConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
package com.jagrosh.jmusicbot;

import com.jagrosh.jmusicbot.entities.Prompt;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import com.jagrosh.jmusicbot.utils.OtherUtil;
import com.jagrosh.jmusicbot.utils.TimeUtil;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.typesafe.config.*;
import java.io.IOException;
Expand Down Expand Up @@ -336,7 +336,7 @@ public long getMaxSeconds()

public String getMaxTime()
{
return FormatUtil.formatTime(maxSeconds * 1000);
return TimeUtil.formatTime(maxSeconds * 1000);
}

public long getAloneTimeUntilStop()
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/jagrosh/jmusicbot/JMusicBot.java
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ private static CommandClient createCommandClient(BotConfig config, SettingsManag
new RemoveCmd(bot),
new SearchCmd(bot),
new SCSearchCmd(bot),
new SeekCmd(bot),
new ShuffleCmd(bot),
new SkipCmd(bot),

Expand Down
4 changes: 3 additions & 1 deletion src/main/java/com/jagrosh/jmusicbot/audio/AudioHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.jagrosh.jmusicbot.playlist.PlaylistLoader.Playlist;
import com.jagrosh.jmusicbot.queue.AbstractQueue;
import com.jagrosh.jmusicbot.settings.QueueType;
import com.jagrosh.jmusicbot.utils.TimeUtil;
import com.jagrosh.jmusicbot.settings.RepeatMode;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
Expand Down Expand Up @@ -50,6 +51,7 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
public final static String PAUSE_EMOJI = "\u23F8"; // ⏸
public final static String STOP_EMOJI = "\u23F9"; // ⏹


private final List<AudioTrack> defaultQueue = new LinkedList<>();
private final Set<String> votes = new HashSet<>();

Expand Down Expand Up @@ -246,7 +248,7 @@ public Message getNowPlaying(JDA jda)
double progress = (double)audioPlayer.getPlayingTrack().getPosition()/track.getDuration();
eb.setDescription(getStatusEmoji()
+ " "+FormatUtil.progressBar(progress)
+ " `[" + FormatUtil.formatTime(track.getPosition()) + "/" + FormatUtil.formatTime(track.getDuration()) + "]` "
+ " `[" + TimeUtil.formatTime(track.getPosition()) + "/" + TimeUtil.formatTime(track.getDuration()) + "]` "
+ FormatUtil.volumeIcon(audioPlayer.getVolume()));

return mb.setEmbeds(eb.build()).build();
Expand Down
23 changes: 14 additions & 9 deletions src/main/java/com/jagrosh/jmusicbot/audio/QueuedTrack.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
*/
package com.jagrosh.jmusicbot.audio;

import com.jagrosh.jmusicbot.utils.TimeUtil;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
import com.jagrosh.jmusicbot.queue.Queueable;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.api.entities.User;

/**
Expand All @@ -28,33 +28,38 @@
public class QueuedTrack implements Queueable
{
private final AudioTrack track;

public QueuedTrack(AudioTrack track, User owner)
{
this(track, new RequestMetadata(owner));
}

private final RequestMetadata requestMetadata;

public QueuedTrack(AudioTrack track, RequestMetadata rm)
{
this.track = track;
this.track.setUserData(rm == null ? RequestMetadata.EMPTY : rm);

this.requestMetadata = rm;
if (this.track.isSeekable() && rm != null)
track.setPosition(rm.requestInfo.startTimestamp);
}

@Override
public long getIdentifier()
{
return track.getUserData() == null ? 0L : track.getUserData(RequestMetadata.class).getOwner();
return requestMetadata.getOwner();
}

public AudioTrack getTrack()
{
return track;
}

public RequestMetadata getRequestMetadata()
{
return requestMetadata;
}

@Override
public String toString()
{
String entry = "`[" + FormatUtil.formatTime(track.getDuration()) + "]` ";
String entry = "`[" + TimeUtil.formatTime(track.getDuration()) + "]` ";
AudioTrackInfo trackInfo = track.getInfo();
entry = entry + (trackInfo.uri.startsWith("http") ? "[**" + trackInfo.title + "**]("+trackInfo.uri+")" : "**" + trackInfo.title + "**");
return entry + " - <@" + track.getUserData(RequestMetadata.class).getOwner() + ">";
Expand Down
41 changes: 34 additions & 7 deletions src/main/java/com/jagrosh/jmusicbot/audio/RequestMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,40 +15,67 @@
*/
package com.jagrosh.jmusicbot.audio;

import com.jagrosh.jdautilities.command.CommandEvent;
import com.jagrosh.jmusicbot.utils.TimeUtil;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import net.dv8tion.jda.api.entities.User;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
*
* @author John Grosh (john.a.grosh@gmail.com)
*/
public class RequestMetadata
{
public static final RequestMetadata EMPTY = new RequestMetadata(null);
public static final RequestMetadata EMPTY = new RequestMetadata(null, null);

public final UserInfo user;
public final RequestInfo requestInfo;

public RequestMetadata(User user)
public RequestMetadata(User user, RequestInfo requestInfo)
{
this.user = user == null ? null : new UserInfo(user.getIdLong(), user.getName(), user.getDiscriminator(), user.getEffectiveAvatarUrl());
this.requestInfo = requestInfo;
}

public long getOwner()
{
return user == null ? 0L : user.id;
}

public static RequestMetadata fromResultHandler(AudioTrack track, CommandEvent event)
{
return new RequestMetadata(event.getAuthor(), new RequestInfo(event.getArgs(), track.getInfo().uri));
}

public class RequestInfo
public static class RequestInfo
{
public final String query, url;

private RequestInfo(String query, String url)
public final long startTimestamp;

public RequestInfo(String query, String url)
{
this(query, url, tryGetTimestamp(query));
}

private RequestInfo(String query, String url, long startTimestamp)
{
this.query = query;
this.url = url;
this.query = query;
this.startTimestamp = startTimestamp;
}

private static final Pattern youtubeTimestampPattern = Pattern.compile("youtu(?:\\.be|be\\..+)/.*\\?.*(?!.*list=)t=([\\dhms]+)");
private static long tryGetTimestamp(String url)
{
Matcher matcher = youtubeTimestampPattern.matcher(url);
return matcher.find() ? TimeUtil.parseUnitTime(matcher.group(1)) : 0;
}
}

public class UserInfo
public static class UserInfo
{
public final long id;
public final String username, discrim, avatar;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.audio.QueuedTrack;
import com.jagrosh.jmusicbot.audio.RequestMetadata;
import com.jagrosh.jmusicbot.commands.DJCommand;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import com.jagrosh.jmusicbot.utils.TimeUtil;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
Expand Down Expand Up @@ -79,13 +81,13 @@ private void loadSingle(AudioTrack track)
if(bot.getConfig().isTooLong(track))
{
m.editMessage(FormatUtil.filter(event.getClient().getWarning()+" This track (**"+track.getInfo().title+"**) is longer than the allowed maximum: `"
+FormatUtil.formatTime(track.getDuration())+"` > `"+FormatUtil.formatTime(bot.getConfig().getMaxSeconds()*1000)+"`")).queue();
+ TimeUtil.formatTime(track.getDuration())+"` > `"+ TimeUtil.formatTime(bot.getConfig().getMaxSeconds()*1000)+"`")).queue();
return;
}
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
int pos = handler.addTrackToFront(new QueuedTrack(track, event.getAuthor()))+1;
int pos = handler.addTrackToFront(new QueuedTrack(track, RequestMetadata.fromResultHandler(track, event)))+1;
String addMsg = FormatUtil.filter(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0?"to begin playing":" to the queue at position "+pos));
+"** (`"+ TimeUtil.formatTime(track.getDuration())+"`) "+(pos==0?"to begin playing":" to the queue at position "+pos));
m.editMessage(addMsg).queue();
}

Expand Down
12 changes: 7 additions & 5 deletions src/main/java/com/jagrosh/jmusicbot/commands/music/PlayCmd.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package com.jagrosh.jmusicbot.commands.music;

import com.jagrosh.jmusicbot.audio.RequestMetadata;
import com.jagrosh.jmusicbot.utils.TimeUtil;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException.Severity;
Expand Down Expand Up @@ -108,13 +110,13 @@ private void loadSingle(AudioTrack track, AudioPlaylist playlist)
if(bot.getConfig().isTooLong(track))
{
m.editMessage(FormatUtil.filter(event.getClient().getWarning()+" This track (**"+track.getInfo().title+"**) is longer than the allowed maximum: `"
+FormatUtil.formatTime(track.getDuration())+"` > `"+FormatUtil.formatTime(bot.getConfig().getMaxSeconds()*1000)+"`")).queue();
+ TimeUtil.formatTime(track.getDuration())+"` > `"+ TimeUtil.formatTime(bot.getConfig().getMaxSeconds()*1000)+"`")).queue();
return;
}
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
int pos = handler.addTrack(new QueuedTrack(track, event.getAuthor()))+1;
int pos = handler.addTrack(new QueuedTrack(track, RequestMetadata.fromResultHandler(track, event)))+1;
String addMsg = FormatUtil.filter(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0?"to begin playing":" to the queue at position "+pos));
+"** (`"+ TimeUtil.formatTime(track.getDuration())+"`) "+(pos==0?"to begin playing":" to the queue at position "+pos));
if(playlist==null || !event.getSelfMember().hasPermission(event.getTextChannel(), Permission.MESSAGE_ADD_REACTION))
m.editMessage(addMsg).queue();
else
Expand Down Expand Up @@ -144,7 +146,7 @@ private int loadPlaylist(AudioPlaylist playlist, AudioTrack exclude)
if(!bot.getConfig().isTooLong(track) && !track.equals(exclude))
{
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
handler.addTrack(new QueuedTrack(track, event.getAuthor()));
handler.addTrack(new QueuedTrack(track, RequestMetadata.fromResultHandler(track, event)));
count[0]++;
}
});
Expand Down Expand Up @@ -243,7 +245,7 @@ public void doCommand(CommandEvent event)
event.getChannel().sendMessage(loadingEmoji+" Loading playlist **"+event.getArgs()+"**... ("+playlist.getItems().size()+" items)").queue(m ->
{
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
playlist.loadTracks(bot.getPlayerManager(), (at)->handler.addTrack(new QueuedTrack(at, event.getAuthor())), () -> {
playlist.loadTracks(bot.getPlayerManager(), (at)->handler.addTrack(new QueuedTrack(at, RequestMetadata.fromResultHandler(at, event))), () -> {
StringBuilder builder = new StringBuilder(playlist.getTracks().isEmpty()
? event.getClient().getWarning()+" No tracks were loaded!"
: event.getClient().getSuccess()+" Loaded **"+playlist.getTracks().size()+"** tracks!");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.jagrosh.jmusicbot.settings.RepeatMode;
import com.jagrosh.jmusicbot.settings.Settings;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import com.jagrosh.jmusicbot.utils.TimeUtil;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Message;
Expand Down Expand Up @@ -112,7 +113,7 @@ private String getQueueTitle(AudioHandler ah, String success, int songslength, l
.append(ah.getPlayer().getPlayingTrack().getInfo().title).append("**\n");
}
return FormatUtil.filter(sb.append(success).append(" Current Queue | ").append(songslength)
.append(" entries | `").append(FormatUtil.formatTime(total)).append("` ")
.append(" entries | `").append(TimeUtil.formatTime(total)).append("` ")
.append("| ").append(queueType.getEmoji()).append(" `").append(queueType.getUserFriendlyName()).append('`')
.append(repeatmode.getEmoji() != null ? " | "+repeatmode.getEmoji() : "").toString());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package com.jagrosh.jmusicbot.commands.music;

import com.jagrosh.jmusicbot.audio.RequestMetadata;
import com.jagrosh.jmusicbot.utils.TimeUtil;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException.Severity;
Expand Down Expand Up @@ -88,13 +90,13 @@ public void trackLoaded(AudioTrack track)
if(bot.getConfig().isTooLong(track))
{
m.editMessage(FormatUtil.filter(event.getClient().getWarning()+" This track (**"+track.getInfo().title+"**) is longer than the allowed maximum: `"
+FormatUtil.formatTime(track.getDuration())+"` > `"+bot.getConfig().getMaxTime()+"`")).queue();
+ TimeUtil.formatTime(track.getDuration())+"` > `"+bot.getConfig().getMaxTime()+"`")).queue();
return;
}
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
int pos = handler.addTrack(new QueuedTrack(track, event.getAuthor()))+1;
int pos = handler.addTrack(new QueuedTrack(track, RequestMetadata.fromResultHandler(track, event)))+1;
m.editMessage(FormatUtil.filter(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
+"** (`"+ TimeUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
: " to the queue at position "+pos))).queue();
}

Expand All @@ -110,13 +112,13 @@ public void playlistLoaded(AudioPlaylist playlist)
if(bot.getConfig().isTooLong(track))
{
event.replyWarning("This track (**"+track.getInfo().title+"**) is longer than the allowed maximum: `"
+FormatUtil.formatTime(track.getDuration())+"` > `"+bot.getConfig().getMaxTime()+"`");
+ TimeUtil.formatTime(track.getDuration())+"` > `"+bot.getConfig().getMaxTime()+"`");
return;
}
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
int pos = handler.addTrack(new QueuedTrack(track, event.getAuthor()))+1;
int pos = handler.addTrack(new QueuedTrack(track, RequestMetadata.fromResultHandler(track, event)))+1;
event.replySuccess("Added **" + FormatUtil.filter(track.getInfo().title)
+ "** (`" + FormatUtil.formatTime(track.getDuration()) + "`) " + (pos==0 ? "to begin playing"
+ "** (`" + TimeUtil.formatTime(track.getDuration()) + "`) " + (pos==0 ? "to begin playing"
: " to the queue at position "+pos));
})
.setCancel((msg) -> {})
Expand All @@ -125,7 +127,7 @@ public void playlistLoaded(AudioPlaylist playlist)
for(int i=0; i<4 && i<playlist.getTracks().size(); i++)
{
AudioTrack track = playlist.getTracks().get(i);
builder.addChoices("`["+FormatUtil.formatTime(track.getDuration())+"]` [**"+track.getInfo().title+"**]("+track.getInfo().uri+")");
builder.addChoices("`["+ TimeUtil.formatTime(track.getDuration())+"]` [**"+track.getInfo().title+"**]("+track.getInfo().uri+")");
}
builder.build().display(m);
}
Expand Down

0 comments on commit 81322ef

Please sign in to comment.