Skip to content

Commit

Permalink
command parser, expand ClientQuestEvents, argument prefix, JDA 4
Browse files Browse the repository at this point in the history
 - create CommandParser that enables escaping meta characters through
   an escape character "\" or using single or doubles quotes and makes
   using arguments smarter and less strict
   - inline arguments are now treated as regular arguments and can be
     used as such, when used as an inline character the value of the
     argument will be the input following the argument up to the next
     argument. The order in which inline arguments are used no longer
     matters. Meaning 'insert a $to b $at c' could also be written
     'insert a $at c $to b' or even 'insert $to=b $at=c a'.
   - argument values may now contain whitespace by putting the value in
     quotes like 'command $arg="some value"'
   - enables using escape characters and quotes to escape meta characters
     e.g. `play $spotify \$trackname` or `play $spotify "$trackname"`
 - enable selecting several options comma separated when asked a question
 - add an option to select all options when asked a question by certain
   commands
 - add property to customise argument prefix
   - create CommandParseListener for the new CommandParser to update
     argument prefixes in existing Presets when changed
 - add monthly charts to charts command
 - help command examples now use the custom prefixes
 - upgrade to JDA 4
 - refactor PlayableFactory to create Playables for Spotify albums and
   playlists and YouTube playlists when they appear in the provided list
   of objects for any method that returns a List of Playables
   - this was done to simplify #withUserResponse implementations if the
     user uses the new feature to select several options
 - create AudioManager#startPlayback and #startOrResumePlayback
   instead of relying on Playable#matches to automatically determine
   whether the current track is the track that should be played or if the
   skip or rewind commands / actions were used because in rare cases the
   Spotify id might be null in which case the method is unreliable
 - add Playable#getDisplayNow and #getDurationNow to use in queue view
   handler instead of using a timeout to further reduce loading time
 - make Playable methods throw an UnavailableResourceException instead of
   InterruptedException when trying to access a cancelled item because
   an InterruptedException does not quite make sense
 - make the the permission all attribute ignore admin commands
 - optimise ThreadExecutionQueue to synchronise #add and #runNext to make
   sure a thread can't be added at the same time as another one finishes
   and tries starting the next one, creating a window where potentially
   one thread to many could run at the same time
 - move GuildManager#getNameForGuild and #getPrefixToGuild to the
   GuildContext so the GuildContext
 - create AdditionalInformationException for exception classes that
   show addition hints, separating the long hint from the error message
 - create session in CommandListener to load bot name and prefix with
   instead of creating a session in both methods
  • Loading branch information
robinfriedli committed Aug 14, 2019
1 parent 6aaaf4f commit 410fcf8
Show file tree
Hide file tree
Showing 140 changed files with 2,327 additions and 1,232 deletions.
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<dependency>
<groupId>com.sedmelluq</groupId>
<artifactId>lavaplayer</artifactId>
<version>1.3.19</version>
<version>1.3.20</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
Expand Down Expand Up @@ -75,7 +75,7 @@
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>3.8.3_462</version>
<version>4.0.0_39</version>
<scope>compile</scope>
</dependency>
<dependency>
Expand All @@ -96,7 +96,7 @@
<dependency>
<groupId>se.michaelthelin.spotify</groupId>
<artifactId>spotify-web-api-java</artifactId>
<version>2.1.2</version>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
Expand Down
2 changes: 1 addition & 1 deletion resources/current-version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.6.1.4
1.6.2
15 changes: 14 additions & 1 deletion resources/versions.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<versions xmlns="versionSpace">
<version launched="false" silent="true" version="1.6.1.4">
<version launched="false" version="1.6.2">
<feature>**new command parser that is smarter at interpreting arguments**
- makes using arguments less strict and inline arguments may now be used wherever you want in the command and they are treated as regular arguments with the input to their right as value
- *meaning `insert track $to listName $at position` could now also be written `insert track $at position $to listName` or even `insert $to=listName $at=position track`*
- enables using escape characters and quotes to escape meta characters e.g. `play $spotify \$trackname` or `play $spotify "$trackname"`
- enables argument values containing whitespace by using quotes like `command $arg="some value"`</feature>
<feature>**enabled selecting several options comma separated when asked a question**</feature>
<feature>**added an option to select all options when asked a question by certain commands**</feature>
<feature>**added property to customise argument prefix**</feature>
<feature>**added monthly charts to charts command**</feature>
<feature>**help command examples now use the custom prefixes**</feature>
<feature>**upgrade to JDA 4**</feature>
</version>
<version launched="true" silent="true" version="1.6.1.4">
<feature>make Spotify redirect smarter</feature>
<feature>add some handling for rare cases when PlaylistTracks have a null track</feature>
</version>
Expand Down
7 changes: 5 additions & 2 deletions resources/xml-contributions/commandInterceptors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
<commandInterceptor order="1" implementation="net.robinfriedli.botify.command.interceptor.interceptors.SecurityInterceptor">
<interruptingException class="net.robinfriedli.botify.exceptions.ForbiddenCommandException"/>
</commandInterceptor>
<commandInterceptor order="2" implementation="net.robinfriedli.botify.command.interceptor.interceptors.CommandVerificationInterceptor">
<commandInterceptor order="2" implementation="net.robinfriedli.botify.command.interceptor.interceptors.CommandParserInterceptor">
<interruptingException class="net.robinfriedli.botify.exceptions.CommandParseException"/>
</commandInterceptor>
<commandInterceptor order="3" implementation="net.robinfriedli.botify.command.interceptor.interceptors.CommandVerificationInterceptor">
<interruptingException class="net.robinfriedli.botify.exceptions.InvalidCommandException"/>
</commandInterceptor>
<commandInterceptor order="3" implementation="net.robinfriedli.botify.command.interceptor.interceptors.HistoryInterceptor"/>
<commandInterceptor order="4" implementation="net.robinfriedli.botify.command.interceptor.interceptors.HistoryInterceptor"/>
</commandInterceptors>
151 changes: 76 additions & 75 deletions resources/xml-contributions/commands.xml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions resources/xml-contributions/guildProperties.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
<guildProperty property="enableAutoPause" name="auto pause" defaultValue="true" implementation="net.robinfriedli.botify.discord.properties.AutoPauseProperty" updateMessage="Set auto pause to %s"/>
<guildProperty property="defaultSource" name="default source" defaultValue="SPOTIFY" implementation="net.robinfriedli.botify.discord.properties.DefaultSourceProperty" updateMessage="Set the default search source to %s"/>
<guildProperty property="defaultListSource" name="default list source" defaultValue="LOCAL" implementation="net.robinfriedli.botify.discord.properties.DefaultListSourceProperty" updateMessage="Set the default list search source to %s"/>
<guildProperty property="argumentPrefix" name="argument prefix" defaultValue="$" implementation="net.robinfriedli.botify.discord.properties.ArgumentPrefixProperty" updateMessage="Set the argument prefix to '%1$s'. Commands now look like this: $botify play %1$sspotify %1$salbum meteora. The default prefix &quot;$&quot; still works as a fallback. All presets containing argument prefixes have been updated."/>
</guildProperties>
8 changes: 4 additions & 4 deletions src/main/java/net/robinfriedli/botify/Botify.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import org.slf4j.LoggerFactory;

import com.wrapper.spotify.SpotifyApi;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.OnlineStatus;
import net.dv8tion.jda.core.hooks.ListenerAdapter;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.OnlineStatus;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.robinfriedli.botify.audio.AudioManager;
import net.robinfriedli.botify.command.CommandManager;
import net.robinfriedli.botify.command.SecurityManager;
Expand Down Expand Up @@ -105,7 +105,7 @@ public static void shutdownListeners() {
* method waits for those threads to finish, causing a deadlock.
*
* @param millisToWait time to wait for pending actions to complete in milliseconds, after this time the bot will
* quit either way
* quit either way
*/
public static void shutdown(long millisToWait) {
Botify botify = get();
Expand Down
32 changes: 19 additions & 13 deletions src/main/java/net/robinfriedli/botify/audio/AudioManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.entities.VoiceChannel;
import net.dv8tion.jda.core.exceptions.InsufficientPermissionException;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.VoiceChannel;
import net.dv8tion.jda.api.exceptions.InsufficientPermissionException;
import net.robinfriedli.botify.audio.spotify.SpotifyService;
import net.robinfriedli.botify.audio.youtube.YouTubeService;
import net.robinfriedli.botify.command.CommandManager;
import net.robinfriedli.botify.command.widgets.NowPlayingWidget;
Expand Down Expand Up @@ -55,7 +56,15 @@ public AudioManager(YouTubeService youTubeService, SessionFactory sessionFactory
guildManager.setAudioManager(this);
}

public void playTrack(Guild guild, @Nullable VoiceChannel channel) {
public void startPlayback(Guild guild, @Nullable VoiceChannel channel) {
playTrack(guild, channel, false);
}

public void startOrResumePlayback(Guild guild, @Nullable VoiceChannel channel) {
playTrack(guild, channel, true);
}

public void playTrack(Guild guild, @Nullable VoiceChannel channel, boolean resumePaused) {
AudioPlayback playback = getPlaybackForGuild(guild);

if (channel != null) {
Expand All @@ -64,15 +73,12 @@ public void playTrack(Guild guild, @Nullable VoiceChannel channel) {
throw new InvalidCommandException("Not in a voice channel");
}

QueueIterator currentQueueIterator = playback.getCurrentQueueIterator();
Playable current = playback.getAudioQueue().getCurrent();
if (!playback.isPaused()
|| (currentQueueIterator != null && !current.matches(currentQueueIterator.getCurrentlyPlaying()))) {
if (playback.isPaused() && resumePaused) {
playback.unpause();
} else {
QueueIterator queueIterator = new QueueIterator(playback, this);
playback.setCurrentQueueIterator(queueIterator);
queueIterator.playNext();
} else {
playback.unpause();
}
}

Expand All @@ -97,8 +103,8 @@ public AudioPlayerManager getPlayerManager() {
return playerManager;
}

public PlayableFactory createPlayableFactory(Guild guild) {
return new PlayableFactory(urlAudioLoader, youTubeService, guildManager.getContextForGuild(guild).getTrackLoadingExecutor());
public PlayableFactory createPlayableFactory(Guild guild, SpotifyService spotifyService) {
return new PlayableFactory(spotifyService, urlAudioLoader, youTubeService, guildManager.getContextForGuild(guild).getTrackLoadingExecutor());
}

void createHistoryEntry(Playable playable, Guild guild) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.entities.MessageChannel;
import net.dv8tion.jda.core.entities.VoiceChannel;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.VoiceChannel;

/**
* There is exactly one AudioPlayback per guild instantiated when initializing the guild. This class holds all information
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package net.robinfriedli.botify.audio;

import java.nio.ByteBuffer;

import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
import net.dv8tion.jda.core.audio.AudioSendHandler;
import net.dv8tion.jda.api.audio.AudioSendHandler;

public class AudioPlayerSendHandler implements AudioSendHandler {

private final AudioPlayer audioPlayer;
private AudioFrame lastFrame;

Expand All @@ -19,8 +22,8 @@ public boolean canProvide() {
}

@Override
public byte[] provide20MsAudio() {
return lastFrame.getData();
public ByteBuffer provide20MsAudio() {
return ByteBuffer.wrap(lastFrame.getData());
}

@Override
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/net/robinfriedli/botify/audio/AudioQueue.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import java.util.stream.IntStream;

import com.google.common.collect.Lists;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Guild;
import net.robinfriedli.botify.Botify;
import net.robinfriedli.botify.discord.properties.ColorSchemeProperty;
import net.robinfriedli.botify.entities.GuildSpecification;
Expand Down Expand Up @@ -167,10 +167,10 @@ public EmbedBuilder buildMessageEmbed(AudioPlayback playback, Guild guild) {

String currentPosition = Util.normalizeMillis(playback.getCurrentPositionMs());
Playable current = getCurrent();
String duration = Util.normalizeMillis(current.getDurationMsInterruptible());
String duration = Util.normalizeMillis(current.durationMs());
embedBuilder.addField(
"Current",
"| " + current.getDisplayInterruptible() + " - " + currentPosition + " / " + duration,
"| " + current.display() + " - " + currentPosition + " / " + duration,
false
);

Expand Down Expand Up @@ -278,7 +278,7 @@ public void clear() {
* Clear the current tracks in this queue
*
* @param retainCurrent keeps the track that is referenced by the currentTrack index in the queue, this is used
* when the track is currently being played
* when the track is currently being played
*/
public void clear(boolean retainCurrent) {
if (!isEmpty() && retainCurrent) {
Expand Down Expand Up @@ -367,7 +367,7 @@ public void randomize() {
* Generates the random queue order when enabling the shuffle option
*
* @param protectCurrent if true this makes sure that the current track will remain in the same position, used
* when the playback is currently playing
* when the playback is currently playing
*/
public void randomize(boolean protectCurrent) {
randomizedOrder.clear();
Expand Down Expand Up @@ -420,8 +420,8 @@ private void appendIcon(StringBuilder builder, String unicode, boolean enabled)
}

private void appendPlayable(StringBuilder trackListBuilder, Playable playable) {
String display = playable.getDisplayInterruptible();
long durationMs = playable.getDurationMsInterruptible();
String display = playable.display();
long durationMs = playable.durationMs();
trackListBuilder.append("| ").append(display).append(" - ").append(Util.normalizeMillis(durationMs)).append(System.lineSeparator());
}

Expand Down
Loading

0 comments on commit 410fcf8

Please sign in to comment.