Compare commits

...
21 Commits
Author SHA1 Message Date
John Grosh 0912de74e9 Merge origin/master 2017-07-04 02:58:24 -04:00
John Grosh 3752e5b9e0 update pom 2017-07-04 02:57:56 -04:00
John Grosh ae62d5771f Update README.md 2017-07-04 02:32:26 -04:00
John Grosh 434749a250 fixed playlist shuffling 2017-07-04 02:19:08 -04:00
John Grosh cb9644d694 playlist load faster and queue command shows np 2017-07-04 01:41:42 -04:00
John Grosh 8f7e53a37c updated config for staying in voice 2017-06-22 02:47:54 -04:00
John Grosh b158e70495 added pause command
use embed for nowplaying
2017-06-22 01:45:11 -04:00
John Grosh ebed4f972a shuffle playlists when a single commented line contains 'shuffle'
fixed role bug
2017-06-22 00:54:51 -04:00
John Grosh f8b15d9591 updated readme
bumped license year
removed unnecessary import
2017-05-21 10:17:44 -04:00
John Grosh ab1e86d4ca Merge origin/master 2017-05-18 19:59:57 -04:00
John Grosh 9da577aa60 updated versions
local file support
less topic spam for the audit log conscious
2017-05-18 19:59:25 -04:00
John Grosh d7f690bd9a Update README.md 2017-04-26 12:42:39 -04:00
John Grosh 0f52bbd170 updated package name
fixed soundcloud search url bug
fixed playlist permission bug
added info to playlists command
bumped versions
2017-04-24 23:49:57 -04:00
John Grosh 61c62032f2 graphics checks 2017-03-26 04:00:27 -04:00
John Grosh eb6be6b589 lib updates
basic playlist support
config updates
2017-03-25 21:35:00 -04:00
John Grosh 25f262c6e4 added pom 2017-03-19 17:54:39 -04:00
John Grosh f1cca0b305 Merge origin/master 2017-03-19 17:51:19 -04:00
John Grosh 6c9a497725 removed guildlist 2017-03-19 17:50:49 -04:00
John Grosh d87b6aa505 Delete _config.yml 2017-01-30 13:41:44 -05:00
John Grosh 269dd7e0a7 Set theme jekyll-theme-architect 2017-01-30 12:26:02 -05:00
John Grosh f9c55ee567 Update README.md 2017-01-27 00:09:36 -05:00
45 changed files with 3749 additions and 2451 deletions

No files matched your search

+201 -201
View File
@@ -1,201 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 John Grosh
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+10 -1
View File
@@ -1,6 +1,8 @@
# JMusicBot
A Discord music bot with a clean interface, and that is easy to set up and run yourself
[![Setup](http://i.imgur.com/VvXYp5j.png)](https://github.com/jagrosh/MusicBot/wiki/Setup)
# Features
* Easy to run (just make sure Java is installed, and run!)
* Fast loading of songs
@@ -9,12 +11,19 @@ A Discord music bot with a clean interface, and that is easy to set up and run y
* Server-specific setup for the "DJ" role that can moderate the music
* Clean and beautiful menus
* Channel-topic playback bar
* Supports many sites, including Youtube, Soundcloud, and more
* Supports many online radio/streams
* Supports local files
* Playlist support (both web/youtube, and local)
# Setup
Please see the [Setup Page](https://github.com/jagrosh/MusicBot/wiki/Setup) in the wiki to run this bot yourself!
# Questions/Suggestions/Bug Reports
If you'd like to suggest changes to how the bot functions, recommend more customization options, or report bugs, feel free to either open an Issue on this repository, or join [my Discord server](https://discord.gg/0p9LSGoRLu6Pet0k).
If you'd like to suggest changes to how the bot functions, recommend more customization options, or report bugs, feel free to either open an [Issue](https://github.com/jagrosh/MusicBot/issues) on this repository, or join [my Discord server](https://discord.gg/0p9LSGoRLu6Pet0k). If you like this bot, be sure to add a star to the libraries that make this possible: [**JDA**](https://github.com/DV8FromTheWorld/JDA) and [**lavaplayer**](https://github.com/sedmelluq/lavaplayer)
# Editing
This bot (and the source code here) is not meant to be edited. The main purpose of having the source public is to show the capabilities of the libraries, and to allow others to understand how the bot works. There are many requirements and dependencies required to edit and compile it, and there will not be support provided for people looking to make changes on their own. Instead, consider making a feature request (see the above section). If you still choose to make edits, please do so in accordance with the Apache 2.0 License.
# Example
![Example](http://i.imgur.com/gxDdlRL.png)
+83
View File
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jagrosh</groupId>
<artifactId>JMusicBot</artifactId>
<version>0.0.7</version>
<packaging>jar</packaging>
<repositories>
<repository>
<id>central</id>
<name>bintray</name>
<url>http://jcenter.bintray.com</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.22</version>
</dependency>
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>3.1.1_219</version>
</dependency>
<dependency>
<groupId>com.sedmelluq</groupId>
<artifactId>lavaplayer</artifactId>
<version>1.2.42</version>
</dependency>
<dependency>
<groupId>com.jagrosh</groupId>
<artifactId>JDA-Utilities</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160810</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.jagrosh.jmusicbot.JMusicBot</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<configuration>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
@@ -1,332 +1,411 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import me.jagrosh.jdautilities.commandclient.Command.Category;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jdautilities.waiter.EventWaiter;
import me.jagrosh.jmusicbot.audio.AudioHandler;
import me.jagrosh.jmusicbot.gui.GUI;
import me.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.VoiceChannel;
import net.dv8tion.jda.core.events.ReadyEvent;
import net.dv8tion.jda.core.events.ShutdownEvent;
import net.dv8tion.jda.core.hooks.ListenerAdapter;
import net.dv8tion.jda.core.utils.PermissionUtil;
import net.dv8tion.jda.core.utils.SimpleLog;
import org.json.JSONException;
import org.json.JSONObject;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class Bot extends ListenerAdapter {
private final HashMap<String,Settings> settings;
private final AudioPlayerManager manager;
private final EventWaiter waiter;
private final ScheduledExecutorService threadpool;
private JDA jda;
private GUI gui;
//private GuildsPanel panel;
public final Category MUSIC = new Category("Music");
public final Category DJ = new Category("DJ", event ->
{
if(event.getAuthor().getId().equals(event.getClient().getOwnerId()))
return true;
if(event.getGuild()==null)
return true;
if(PermissionUtil.checkPermission(event.getGuild(), event.getMember(), Permission.MANAGE_SERVER))
return true;
Role dj = event.getGuild().getRoleById(getSettings(event.getGuild()).getRoleId());
return event.getMember().getRoles().contains(dj);
});
public final Category ADMIN = new Category("Admin", event ->
{
if(event.getAuthor().getId().equals(event.getClient().getOwnerId()))
return true;
if(event.getGuild()==null)
return true;
return PermissionUtil.checkPermission(event.getGuild(), event.getMember(), Permission.MANAGE_SERVER);
});
public final Category OWNER = new Category("Owner");
public Bot(EventWaiter waiter)
{
this.waiter = waiter;
this.settings = new HashMap<>();
manager = new DefaultAudioPlayerManager();
threadpool = Executors.newSingleThreadScheduledExecutor();
AudioSourceManagers.registerRemoteSources(manager);
try {
JSONObject loadedSettings = new JSONObject(new String(Files.readAllBytes(Paths.get("serversettings.json"))));
for(String id: loadedSettings.keySet())
{
JSONObject o = loadedSettings.getJSONObject(id);
settings.put(id, new Settings(o.has("text_channel_id")?o.getString("text_channel_id"):null,
o.has("voice_channel_id")?o.getString("voice_channel_id"):null,
o.has("dj_role_id")?o.getString("dj_role_id"):null));
}
} catch(IOException | JSONException e) {
SimpleLog.getLog("Settings").warn("Failed to load server settings: "+e);
}
}
public EventWaiter getWaiter()
{
return waiter;
}
public AudioPlayerManager getAudioManager()
{
return manager;
}
public int queueTrack(CommandEvent event, AudioTrack track)
{
return setUpHandler(event).addTrack(track, event.getAuthor());
}
public AudioHandler setUpHandler(CommandEvent event)
{
AudioHandler handler;
if(event.getGuild().getAudioManager().getSendingHandler()==null)
{
AudioPlayer player = manager.createPlayer();
handler = new AudioHandler(player, event.getGuild());
player.addListener(handler);
event.getGuild().getAudioManager().setSendingHandler(handler);
threadpool.scheduleWithFixedDelay(() -> updateTopic(event.getGuild(),handler), 0, 5, TimeUnit.SECONDS);
}
else
{
handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
}
return handler;
}
private void updateTopic(Guild guild, AudioHandler handler)
{
TextChannel tchan = guild.getTextChannelById(getSettings(guild).getTextId());
if(tchan!=null && PermissionUtil.checkPermission(tchan, guild.getSelfMember(), Permission.MANAGE_CHANNEL))
{
String otherText;
if(tchan.getTopic()==null || tchan.getTopic().isEmpty())
otherText = "";
else if(tchan.getTopic().contains("\u200B"))
otherText = tchan.getTopic().substring(tchan.getTopic().indexOf("\u200B"));
else
otherText = "\u200B\n "+tchan.getTopic();
String text = FormatUtil.formattedAudio(handler, guild.getJDA(), true)+otherText;
if(!text.equals(tchan.getTopic()))
tchan.getManager().setTopic(text).queue();
}
}
public void shutdown(){
manager.shutdown();
threadpool.shutdownNow();
jda.getGuilds().stream().forEach(g -> {
g.getAudioManager().closeAudioConnection();
AudioHandler ah = (AudioHandler)g.getAudioManager().getSendingHandler();
if(ah!=null)
{
ah.getQueue().clear();
ah.getPlayer().destroy();
updateTopic(g, ah);
}
});
jda.shutdown();
}
public void setGUI(GUI gui)
{
this.gui = gui;
}
@Override
public void onShutdown(ShutdownEvent event) {
if(gui!=null)
gui.dispose();
}
@Override
public void onReady(ReadyEvent event) {
this.jda = event.getJDA();
//if(panel!=null)
// panel.updateList(event.getJDA().getGuilds());
}
// settings
public Settings getSettings(Guild guild)
{
return settings.getOrDefault(guild.getId(), Settings.DEFAULT_SETTINGS);
}
public void setTextChannel(TextChannel channel)
{
Settings s = settings.get(channel.getGuild().getId());
if(s==null)
{
settings.put(channel.getGuild().getId(), new Settings(channel.getId(),null,null));
}
else
{
s.setTextId(channel.getId());
}
writeSettings();
}
public void setVoiceChannel(VoiceChannel channel)
{
Settings s = settings.get(channel.getGuild().getId());
if(s==null)
{
settings.put(channel.getGuild().getId(), new Settings(null,channel.getId(),null));
}
else
{
s.setVoiceId(channel.getId());
}
writeSettings();
}
public void setRole(Role role)
{
Settings s = settings.get(role.getGuild().getId());
if(s==null)
{
settings.put(role.getGuild().getId(), new Settings(null,null,role.getId()));
}
else
{
s.setRoleId(role.getId());
}
writeSettings();
}
public void clearTextChannel(Guild guild)
{
Settings s = getSettings(guild);
if(s!=null)
{
if(s.getVoiceId()==null && s.getRoleId()==null)
settings.remove(guild.getId());
else
s.setTextId(null);
writeSettings();
}
}
public void clearVoiceChannel(Guild guild)
{
Settings s = getSettings(guild);
if(s!=null)
{
if(s.getTextId()==null && s.getRoleId()==null)
settings.remove(guild.getId());
else
s.setVoiceId(null);
writeSettings();
}
}
public void clearRole(Guild guild)
{
Settings s = getSettings(guild);
if(s!=null)
{
if(s.getVoiceId()==null && s.getTextId()==null)
settings.remove(guild.getId());
else
s.setRoleId(null);
writeSettings();
}
}
private void writeSettings()
{
JSONObject obj = new JSONObject();
settings.keySet().stream().forEach(key -> {
JSONObject o = new JSONObject();
Settings s = settings.get(key);
if(s.getTextId()!=null)
o.put("text_channel_id", s.getTextId());
if(s.getVoiceId()!=null)
o.put("voice_channel_id", s.getVoiceId());
if(s.getRoleId()!=null)
o.put("dj_role_id", s.getRoleId());
obj.put(key, o);
});
try {
Files.write(Paths.get("serversettings.json"), obj.toString(4).getBytes());
} catch(IOException ex){
SimpleLog.getLog("Settings").warn("Failed to write to file: "+ex);
}
}
//gui stuff
/*public void registerPanel(GuildsPanel panel)
{
this.panel = panel;
threadpool.scheduleWithFixedDelay(() -> updatePanel(), 0, 5, TimeUnit.SECONDS);
}
public void updatePanel()
{
System.out.println("updating...");
Guild guild = jda.getGuilds().get(panel.getIndex());
panel.updatePanel((AudioHandler)guild.getAudioManager().getSendingHandler());
}
@Override
public void onGuildJoin(GuildJoinEvent event) {
if(panel!=null)
panel.updateList(event.getJDA().getGuilds());
}
@Override
public void onGuildLeave(GuildLeaveEvent event) {
if(panel!=null)
panel.updateList(event.getJDA().getGuilds());
}
@Override
public void onShutdown(ShutdownEvent event) {
((GUI)panel.getTopLevelAncestor()).dispose();
}*/
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.jagrosh.jdautilities.commandclient.Command.Category;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jdautilities.waiter.EventWaiter;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.gui.GUI;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.VoiceChannel;
import net.dv8tion.jda.core.events.ReadyEvent;
import net.dv8tion.jda.core.events.ShutdownEvent;
import net.dv8tion.jda.core.events.guild.GuildJoinEvent;
import net.dv8tion.jda.core.hooks.ListenerAdapter;
import net.dv8tion.jda.core.utils.SimpleLog;
import org.json.JSONException;
import org.json.JSONObject;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class Bot extends ListenerAdapter {
private final HashMap<String,Settings> settings;
private final AudioPlayerManager manager;
private final EventWaiter waiter;
private final ScheduledExecutorService threadpool;
private final Config config;
private JDA jda;
private GUI gui;
//private GuildsPanel panel;
public final Category MUSIC = new Category("Music");
public final Category DJ = new Category("DJ", event ->
{
if(event.getAuthor().getId().equals(event.getClient().getOwnerId()))
return true;
if(event.getGuild()==null)
return true;
if(event.getMember().hasPermission(Permission.MANAGE_SERVER))
return true;
Role dj = event.getGuild().getRoleById(getSettings(event.getGuild()).getRoleId());
return event.getMember().getRoles().contains(dj);
});
public final Category ADMIN = new Category("Admin", event ->
{
if(event.getAuthor().getId().equals(event.getClient().getOwnerId()))
return true;
if(event.getGuild()==null)
return true;
return event.getMember().hasPermission(Permission.MANAGE_SERVER);
});
public final Category OWNER = new Category("Owner");
public Bot(EventWaiter waiter, Config config)
{
this.config = config;
this.waiter = waiter;
this.settings = new HashMap<>();
manager = new DefaultAudioPlayerManager();
threadpool = Executors.newSingleThreadScheduledExecutor();
AudioSourceManagers.registerRemoteSources(manager);
AudioSourceManagers.registerLocalSource(manager);
try {
JSONObject loadedSettings = new JSONObject(new String(Files.readAllBytes(Paths.get("serversettings.json"))));
loadedSettings.keySet().forEach((id) -> {
JSONObject o = loadedSettings.getJSONObject(id);
settings.put(id, new Settings(
o.has("text_channel_id") ? o.getString("text_channel_id") : null,
o.has("voice_channel_id")? o.getString("voice_channel_id"): null,
o.has("dj_role_id") ? o.getString("dj_role_id") : null,
o.has("volume") ? o.getInt("volume") : 100,
o.has("default_playlist")? o.getString("default_playlist"): null));
});
} catch(IOException | JSONException e) {
SimpleLog.getLog("Settings").warn("Failed to load server settings: "+e);
}
}
public EventWaiter getWaiter()
{
return waiter;
}
public AudioPlayerManager getAudioManager()
{
return manager;
}
public int queueTrack(CommandEvent event, AudioTrack track)
{
return setUpHandler(event).addTrack(track, event.getAuthor());
}
public AudioHandler setUpHandler(CommandEvent event)
{
return setUpHandler(event.getGuild());
}
public AudioHandler setUpHandler(Guild guild)
{
AudioHandler handler;
if(guild.getAudioManager().getSendingHandler()==null)
{
AudioPlayer player = manager.createPlayer();
if(settings.containsKey(guild.getId()))
player.setVolume(settings.get(guild.getId()).getVolume());
handler = new AudioHandler(player, guild, this);
player.addListener(handler);
guild.getAudioManager().setSendingHandler(handler);
threadpool.scheduleWithFixedDelay(() -> updateTopic(guild,handler), 0, 5, TimeUnit.SECONDS);
}
else
handler = (AudioHandler)guild.getAudioManager().getSendingHandler();
return handler;
}
private void updateTopic(Guild guild, AudioHandler handler)
{
TextChannel tchan = guild.getTextChannelById(getSettings(guild).getTextId());
if(tchan!=null && guild.getSelfMember().hasPermission(tchan, Permission.MANAGE_CHANNEL))
{
String otherText;
if(tchan.getTopic()==null || tchan.getTopic().isEmpty())
otherText = "\u200B";
else if(tchan.getTopic().contains("\u200B"))
otherText = tchan.getTopic().substring(tchan.getTopic().indexOf("\u200B"));
else
otherText = "\u200B\n "+tchan.getTopic();
String text = FormatUtil.formattedAudio(handler, guild.getJDA())+otherText;
if(!text.equals(tchan.getTopic()))
tchan.getManager().setTopic(text).queue();
}
}
public void shutdown(){
manager.shutdown();
threadpool.shutdownNow();
jda.getGuilds().stream().forEach(g -> {
g.getAudioManager().closeAudioConnection();
AudioHandler ah = (AudioHandler)g.getAudioManager().getSendingHandler();
if(ah!=null)
{
ah.getQueue().clear();
ah.getPlayer().destroy();
updateTopic(g, ah);
}
});
jda.shutdown();
}
public void setGUI(GUI gui)
{
this.gui = gui;
}
@Override
public void onShutdown(ShutdownEvent event) {
if(gui!=null)
gui.dispose();
}
@Override
public void onReady(ReadyEvent event) {
this.jda = event.getJDA();
if(jda.getGuilds().isEmpty())
{
SimpleLog.getLog("MusicBot").warn("This bot is not on any guilds! Use the following link to add the bot to your guilds!");
SimpleLog.getLog("MusicBot").warn(event.getJDA().asBot().getInviteUrl(JMusicBot.RECOMMENDED_PERMS));
}
credit(event.getJDA());
jda.getGuilds().forEach((guild) -> {
try
{
String defpl = getSettings(guild).getDefaultPlaylist();
VoiceChannel vc = guild.getVoiceChannelById(getSettings(guild).getVoiceId());
if(defpl!=null && vc!=null)
{
if(setUpHandler(guild).playFromDefault())
guild.getAudioManager().openAudioConnection(vc);
}
}
catch(Exception ex) {System.err.println(ex);}
});
}
@Override
public void onGuildJoin(GuildJoinEvent event) {
credit(event.getJDA());
}
// make sure people aren't adding clones to dbots
private void credit(JDA jda)
{
Guild dbots = jda.getGuildById(110373943822540800L);
if(dbots==null)
return;
if(config.getDBots())
return;
jda.getTextChannelById(119222314964353025L)
.sendMessage("<@113156185389092864>: This account is running JMusicBot. Please do not list bot clones on this server, <@"+config.getOwnerId()+">.").complete();
dbots.leave().queue();
}
// settings
public Settings getSettings(Guild guild)
{
return settings.getOrDefault(guild.getId(), Settings.DEFAULT_SETTINGS);
}
public void setTextChannel(TextChannel channel)
{
Settings s = settings.get(channel.getGuild().getId());
if(s==null)
{
settings.put(channel.getGuild().getId(), new Settings(channel.getId(),null,null,100,null));
}
else
{
s.setTextId(channel.getIdLong());
}
writeSettings();
}
public void setVoiceChannel(VoiceChannel channel)
{
Settings s = settings.get(channel.getGuild().getId());
if(s==null)
{
settings.put(channel.getGuild().getId(), new Settings(null,channel.getId(),null,100,null));
}
else
{
s.setVoiceId(channel.getIdLong());
}
writeSettings();
}
public void setRole(Role role)
{
Settings s = settings.get(role.getGuild().getId());
if(s==null)
{
settings.put(role.getGuild().getId(), new Settings(null,null,role.getId(),100,null));
}
else
{
s.setRoleId(role.getIdLong());
}
writeSettings();
}
public void setDefaultPlaylist(Guild guild, String playlist)
{
Settings s = settings.get(guild.getId());
if(s==null)
{
settings.put(guild.getId(), new Settings(null,null,null,100,playlist));
}
else
{
s.setDefaultPlaylist(playlist);
}
writeSettings();
}
public void setVolume(Guild guild, int volume)
{
Settings s = settings.get(guild.getId());
if(s==null)
{
settings.put(guild.getId(), new Settings(null,null,null,volume,null));
}
else
{
s.setVolume(volume);
}
writeSettings();
}
public void clearTextChannel(Guild guild)
{
Settings s = getSettings(guild);
if(s!=Settings.DEFAULT_SETTINGS)
{
if(s.getVoiceId()==0 && s.getRoleId()==0)
settings.remove(guild.getId());
else
s.setTextId(0);
writeSettings();
}
}
public void clearVoiceChannel(Guild guild)
{
Settings s = getSettings(guild);
if(s!=Settings.DEFAULT_SETTINGS)
{
if(s.getTextId()==0 && s.getRoleId()==0)
settings.remove(guild.getId());
else
s.setVoiceId(0);
writeSettings();
}
}
public void clearRole(Guild guild)
{
Settings s = getSettings(guild);
if(s!=Settings.DEFAULT_SETTINGS)
{
if(s.getVoiceId()==0 && s.getTextId()==0)
settings.remove(guild.getId());
else
s.setRoleId(0);
writeSettings();
}
}
private void writeSettings()
{
JSONObject obj = new JSONObject();
settings.keySet().stream().forEach(key -> {
JSONObject o = new JSONObject();
Settings s = settings.get(key);
if(s.getTextId()!=0)
o.put("text_channel_id", Long.toString(s.getTextId()));
if(s.getVoiceId()!=0)
o.put("voice_channel_id", Long.toString(s.getVoiceId()));
if(s.getRoleId()!=0)
o.put("dj_role_id", Long.toString(s.getRoleId()));
if(s.getVolume()!=100)
o.put("volume",s.getVolume());
if(s.getDefaultPlaylist()!=null)
o.put("default_playlist", s.getDefaultPlaylist());
obj.put(key, o);
});
try {
Files.write(Paths.get("serversettings.json"), obj.toString(4).getBytes());
} catch(IOException ex){
SimpleLog.getLog("Settings").warn("Failed to write to file: "+ex);
}
}
//gui stuff
/*public void registerPanel(GuildsPanel panel)
{
this.panel = panel;
threadpool.scheduleWithFixedDelay(() -> updatePanel(), 0, 5, TimeUnit.SECONDS);
}
public void updatePanel()
{
System.out.println("updating...");
Guild guild = jda.getGuilds().get(panel.getIndex());
panel.updatePanel((AudioHandler)guild.getAudioManager().getSendingHandler());
}
@Override
public void onGuildJoin(GuildJoinEvent event) {
if(panel!=null)
panel.updateList(event.getJDA().getGuilds());
}
@Override
public void onGuildLeave(GuildLeaveEvent event) {
if(panel!=null)
panel.updateList(event.getJDA().getGuilds());
}
@Override
public void onShutdown(ShutdownEvent event) {
((GUI)panel.getTopLevelAncestor()).dispose();
}*/
}
@@ -1,177 +1,236 @@
/*
* Copyright 2016 John Grosh (jagrosh)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import javax.swing.JOptionPane;
/**
*
* @author John Grosh (jagrosh)
*/
public class Config {
private final boolean nogui;
private String prefix;
private String token;
private String owner;
private String success;
private String warning;
private String error;
public Config(boolean nogui)
{
this.nogui = nogui;
List<String> lines;
try {
lines = Files.readAllLines(Paths.get("config.txt"));
for(String line: lines)
{
String[] parts = line.split("=",2);
String key = parts[0].trim().toLowerCase();
String value = parts.length>1 ? parts[1].trim() : null;
switch(key)
{
case "token":
token = value;
break;
case "prefix":
prefix = value;
break;
case "owner":
owner = value;
break;
case "success":
success = value;
break;
case "warning":
warning = value;
break;
case "error":
error = value;
break;
}
}
} catch (IOException ex) {
alert("'config.txt' was not found!");
lines = new LinkedList<>();
}
boolean write = false;
if(token==null || token.isEmpty())
{
token = prompt("Please provide a bot token."
+ "\nInstructions for obtaining a token can be found here:"
+ "\nhttps://github.com/jagrosh/MusicBot/wiki/Getting-a-Bot-Token."
+ "\nBot Token: ");
if(token==null)
{
alert("No token provided! Exiting.");
System.exit(0);
}
else
{
lines.add("token="+token);
write = true;
}
}
if(owner==null || !owner.matches("\\d{17,20}"))
{
owner = prompt("Owner ID was missing, or the provided owner ID is not valid."
+ "\nPlease provide the User ID of the bot's owner."
+ "\nInstructions for obtaining your User ID can be found here:"
+ "\nhttps://github.com/jagrosh/MusicBot/wiki/Finding-Your-User-ID"
+ "\nOwner User ID: ");
if(owner==null || !owner.matches("\\d{17,20}"))
{
alert("Invalid User ID! Exiting.");
System.exit(0);
}
else
{
lines.add("owner="+owner);
write = true;
}
}
if(write)
{
StringBuilder builder = new StringBuilder();
lines.stream().forEach(s -> builder.append(s).append("\r\n"));
try {
Files.write(Paths.get("config.txt"), builder.toString().trim().getBytes());
} catch(IOException ex) {
alert("Failed to write new config options to config.txt: "+ex);
}
}
}
public String getPrefix()
{
return prefix;
}
public String getToken()
{
return token;
}
public String getOwnerId()
{
return owner;
}
public String getSuccess()
{
return success==null ? "\uD83C\uDFB6" : success;
}
public String getWarning()
{
return warning==null ? "\uD83D\uDCA1" : warning;
}
public String getError()
{
return error==null ? "\uD83D\uDEAB" : error;
}
private void alert(String message)
{
if(nogui)
System.out.println("[WARNING] "+message);
else
{
JOptionPane.showMessageDialog(null, message, "JMusicBot", JOptionPane.WARNING_MESSAGE);
}
}
private String prompt(String content)
{
if(nogui)
{
Scanner scanner = new Scanner(System.in);
System.out.println(content);
return scanner.next();
}
else
{
return JOptionPane.showInputDialog(null, content, "JMusicBot", JOptionPane.WARNING_MESSAGE);
}
}
}
/*
* Copyright 2016 John Grosh (jagrosh)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import javax.swing.JOptionPane;
/**
*
* @author John Grosh (jagrosh)
*/
public class Config {
private boolean nogui;
private String prefix;
private String token;
private String owner;
private String success;
private String warning;
private String error;
private String game;
private String help;
private boolean stay;
private boolean dbots;
public Config(boolean nogui)
{
this.nogui = nogui;
List<String> lines;
try {
lines = Files.readAllLines(Paths.get("config.txt"));
System.out.println("[INFO] Loading config: "+Paths.get("config.txt").toFile().getAbsolutePath());
for(String line: lines)
{
String[] parts = line.split("=",2);
String key = parts[0].trim().toLowerCase();
String value = parts.length>1 ? parts[1].trim() : null;
switch(key)
{
case "token":
token = value;
break;
case "prefix":
prefix = value;
break;
case "owner":
owner = value;
break;
case "success":
success = value;
break;
case "warning":
warning = value;
break;
case "error":
error = value;
break;
case "game":
game = value;
break;
case "help":
help = value;
break;
case "noprogressintopic":
FormatUtil.NO_PROGRESS_BAR_IN_TOPIC = "true".equalsIgnoreCase(value);
break;
case "stayinchannel":
stay = "true".equalsIgnoreCase(value);
break;
case "dbots":
dbots = "110373943822540800".equals(value);
break;
}
}
} catch (IOException ex) {
alert("'config.txt' was not found!");
lines = new LinkedList<>();
}
boolean write = false;
if(token==null || token.isEmpty())
{
token = prompt("Please provide a bot token."
+ "\nInstructions for obtaining a token can be found here:"
+ "\nhttps://github.com/jagrosh/MusicBot/wiki/Getting-a-Bot-Token."
+ "\nBot Token: ");
if(token==null)
{
alert("No token provided! Exiting.");
System.exit(0);
}
else
{
lines.add("token="+token);
write = true;
}
}
if(owner==null || !owner.matches("\\d{17,20}"))
{
owner = prompt("Owner ID was missing, or the provided owner ID is not valid."
+ "\nPlease provide the User ID of the bot's owner."
+ "\nInstructions for obtaining your User ID can be found here:"
+ "\nhttps://github.com/jagrosh/MusicBot/wiki/Finding-Your-User-ID"
+ "\nOwner User ID: ");
if(owner==null || !owner.matches("\\d{17,20}"))
{
alert("Invalid User ID! Exiting.");
System.exit(0);
}
else
{
lines.add("owner="+owner);
write = true;
}
}
if(write)
{
StringBuilder builder = new StringBuilder();
lines.stream().forEach(s -> builder.append(s).append("\r\n"));
try {
Files.write(Paths.get("config.txt"), builder.toString().trim().getBytes());
} catch(IOException ex) {
alert("Failed to write new config options to config.txt: "+ex
+ "\nPlease make sure that the files are not on your desktop or some other restricted area.");
}
}
}
public String getPrefix()
{
return prefix;
}
public String getToken()
{
return token;
}
public String getOwnerId()
{
return owner;
}
public String getSuccess()
{
return success==null ? "\uD83C\uDFB6" : success;
}
public String getWarning()
{
return warning==null ? "\uD83D\uDCA1" : warning;
}
public String getError()
{
return error==null ? "\uD83D\uDEAB" : error;
}
public String getGame()
{
return game;
}
public String getHelp()
{
return help==null ? "help" : help;
}
public boolean getNoGui()
{
return nogui;
}
public boolean getStay()
{
return stay;
}
public boolean getDBots()
{
return dbots;
}
private void alert(String message)
{
if(nogui)
System.out.println("[WARNING] "+message);
else
{
try {
JOptionPane.showMessageDialog(null, message, "JMusicBot", JOptionPane.WARNING_MESSAGE);
} catch(Exception e) {
nogui = true;
alert("Switching to nogui mode. You can manually start in nogui mode by including the -nogui flag.");
alert(message);
}
}
}
private String prompt(String content)
{
if(nogui)
{
Scanner scanner = new Scanner(System.in);
System.out.println(content);
return scanner.next();
}
else
{
try {
return JOptionPane.showInputDialog(null, content, "JMusicBot", JOptionPane.WARNING_MESSAGE);
} catch(Exception e) {
nogui = true;
alert("Switching to nogui mode. You can manually start in nogui mode by including the -nogui flag.");
return prompt(content);
}
}
}
}
@@ -1,121 +1,140 @@
/*
* Copyright 2016 John Grosh (jagrosh).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot;
import java.awt.Color;
import javax.security.auth.login.LoginException;
import me.jagrosh.jdautilities.commandclient.CommandClient;
import me.jagrosh.jdautilities.commandclient.CommandClientBuilder;
import me.jagrosh.jdautilities.commandclient.examples.*;
import me.jagrosh.jdautilities.waiter.EventWaiter;
import me.jagrosh.jmusicbot.commands.*;
import me.jagrosh.jmusicbot.gui.GUI;
import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDABuilder;
import net.dv8tion.jda.core.OnlineStatus;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Game;
import net.dv8tion.jda.core.exceptions.RateLimitedException;
import net.dv8tion.jda.core.utils.SimpleLog;
/**
*
* @author John Grosh (jagrosh)
*/
public class JMusicBot {
/**
* @param args the command line arguments
*/
public static void main(String[] args){
// check run mode(s)
boolean nogui = false;
for(String arg: args)
if("-nogui".equalsIgnoreCase(arg))
nogui = true;
// load config
Config config = new Config(nogui);
// set up the listener
EventWaiter waiter = new EventWaiter();
Bot bot = new Bot(waiter);
AboutCommand.IS_AUTHOR = false;
// set up the command client
CommandClient client = new CommandClientBuilder()
.setPrefix(config.getPrefix())
.setOwnerId(config.getOwnerId())
.setEmojis(config.getSuccess(), config.getWarning(), config.getError())
.addCommands(
new AboutCommand(Color.BLUE.brighter(),
"a music bot that is [easy to host yourself!](https://github.com/jagrosh/MusicBot)",
new String[]{"High-quality music playback", "FairQueue™ Technology", "Easy to host yourself"},
Permission.MESSAGE_READ, Permission.MESSAGE_WRITE, Permission.MESSAGE_HISTORY, Permission.MESSAGE_ADD_REACTION,
Permission.MESSAGE_EMBED_LINKS, Permission.MESSAGE_ATTACH_FILES, Permission.MESSAGE_MANAGE, Permission.MESSAGE_EXT_EMOJI,
Permission.MANAGE_CHANNEL, Permission.VOICE_CONNECT, Permission.VOICE_SPEAK, Permission.NICKNAME_CHANGE),
new PingCommand(),
new SettingsCmd(bot),
new NowplayingCmd(bot),
new PlayCmd(bot),
new QueueCmd(bot),
new RemoveCmd(bot),
new SearchCmd(bot),
new ShuffleCmd(bot),
new SkipCmd(bot),
new ForceskipCmd(bot),
new SkiptoCmd(bot),
new StopCmd(bot),
new VolumeCmd(bot),
new SetdjCmd(bot),
new SettcCmd(bot),
new SetvcCmd(bot),
new GuildlistCommand(waiter),
new SetavatarCmd(bot),
new SetgameCmd(bot),
new SetnameCmd(bot),
new ShutdownCmd(bot)
).build();
if(!nogui)
{
GUI gui = new GUI(bot);
bot.setGUI(gui);
gui.init();
}
// attempt to log in and start
try {
new JDABuilder(AccountType.BOT)
.setToken(config.getToken())
.setAudioEnabled(true)
.setGame(Game.of("loading..."))
.setStatus(OnlineStatus.DO_NOT_DISTURB)
.addListener(client)
.addListener(waiter)
.addListener(bot)
.buildAsync();
} catch (LoginException | IllegalArgumentException | RateLimitedException ex) {
SimpleLog.getLog("Login").fatal(ex);
}
}
}
/*
* Copyright 2016 John Grosh (jagrosh).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot;
import java.awt.Color;
import javax.security.auth.login.LoginException;
import com.jagrosh.jdautilities.commandclient.CommandClient;
import com.jagrosh.jdautilities.commandclient.CommandClientBuilder;
import com.jagrosh.jdautilities.commandclient.examples.*;
import com.jagrosh.jdautilities.waiter.EventWaiter;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.commands.*;
import com.jagrosh.jmusicbot.gui.GUI;
import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDABuilder;
import net.dv8tion.jda.core.OnlineStatus;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Game;
import net.dv8tion.jda.core.exceptions.RateLimitedException;
import net.dv8tion.jda.core.utils.SimpleLog;
/**
*
* @author John Grosh (jagrosh)
*/
public class JMusicBot {
public static Permission[] RECOMMENDED_PERMS = new Permission[]{Permission.MESSAGE_READ, Permission.MESSAGE_WRITE, Permission.MESSAGE_HISTORY, Permission.MESSAGE_ADD_REACTION,
Permission.MESSAGE_EMBED_LINKS, Permission.MESSAGE_ATTACH_FILES, Permission.MESSAGE_MANAGE, Permission.MESSAGE_EXT_EMOJI,
Permission.MANAGE_CHANNEL, Permission.VOICE_CONNECT, Permission.VOICE_SPEAK, Permission.NICKNAME_CHANGE};
/**
* @param args the command line arguments
*/
public static void main(String[] args){
// check run mode(s)
boolean nogui = false;
for(String arg: args)
if("-nogui".equalsIgnoreCase(arg))
nogui = true;
// load config
Config config = new Config(nogui);
// set up the listener
EventWaiter waiter = new EventWaiter();
Bot bot = new Bot(waiter, config);
AboutCommand.IS_AUTHOR = false;
AudioHandler.STAY_IN_CHANNEL = config.getStay();
// set up the command client
CommandClientBuilder cb = new CommandClientBuilder()
.setPrefix(config.getPrefix())
.setOwnerId(config.getOwnerId())
.setEmojis(config.getSuccess(), config.getWarning(), config.getError())
.setHelpWord(config.getHelp())
.addCommands(
new AboutCommand(Color.BLUE.brighter(),
"a music bot that is [easy to host yourself!](https://github.com/jagrosh/MusicBot) (v0.0.7)",
new String[]{"High-quality music playback", "FairQueue™ Technology", "Easy to host yourself"},
RECOMMENDED_PERMS),
new PingCommand(),
new SettingsCmd(bot),
new NowplayingCmd(bot),
new PlayCmd(bot),
new PlaylistsCmd(bot),
new QueueCmd(bot),
new RemoveCmd(bot),
new SearchCmd(bot),
new SCSearchCmd(bot),
new ShuffleCmd(bot),
new SkipCmd(bot),
new ForceskipCmd(bot),
new PauseCmd(bot),
new SkiptoCmd(bot),
new StopCmd(bot),
new VolumeCmd(bot),
new SetdjCmd(bot),
new SettcCmd(bot),
new SetvcCmd(bot),
//new GuildlistCommand(waiter),
new PlaylistCmd(bot),
new SetavatarCmd(bot),
new SetgameCmd(bot),
new SetnameCmd(bot),
new ShutdownCmd(bot)
);
if(config.getGame()==null)
cb.useDefaultGame();
else
cb.setGame(Game.of(config.getGame()));
CommandClient client = cb.build();
if(!config.getNoGui())
{
try {
GUI gui = new GUI(bot);
bot.setGUI(gui);
gui.init();
} catch(Exception e) {
SimpleLog.getLog("Startup").fatal("Could not start GUI. If you are "
+ "running on a server or in a location where you cannot display a "
+ "window, please run in nogui mode using the -nogui flag.");
}
}
// attempt to log in and start
try {
new JDABuilder(AccountType.BOT)
.setToken(config.getToken())
.setAudioEnabled(true)
.setGame(Game.of("loading..."))
.setStatus(OnlineStatus.DO_NOT_DISTURB)
.addEventListener(client)
.addEventListener(waiter)
.addEventListener(bot)
.buildAsync();
} catch (LoginException | IllegalArgumentException | RateLimitedException ex) {
SimpleLog.getLog("Login").fatal(ex);
}
}
}
@@ -0,0 +1,121 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class Settings {
public final static Settings DEFAULT_SETTINGS = new Settings(0, 0, 0, 100, null);
private long textId;
private long voiceId;
private long roleId;
private int volume;
private String defaultPlaylist;
public Settings(String textId, String voiceId, String roleId, int volume, String defaultPlaylist)
{
try
{
this.textId = Long.parseLong(textId);
}
catch(NumberFormatException e)
{
this.textId = 0;
}
try
{
this.voiceId = Long.parseLong(voiceId);
}
catch(NumberFormatException e)
{
this.voiceId = 0;
}
try
{
this.roleId = Long.parseLong(roleId);
}
catch(NumberFormatException e)
{
this.roleId = 0;
}
this.volume = volume;
this.defaultPlaylist = defaultPlaylist;
}
public Settings(long textId, long voiceId, long roleId, int volume, String defaultPlaylist)
{
this.textId = textId;
this.voiceId = voiceId;
this.roleId = roleId;
this.volume = volume;
this.defaultPlaylist = defaultPlaylist;
}
public long getTextId()
{
return textId;
}
public long getVoiceId()
{
return voiceId;
}
public long getRoleId()
{
return roleId;
}
public int getVolume()
{
return volume;
}
public String getDefaultPlaylist()
{
return defaultPlaylist;
}
public void setTextId(long id)
{
this.textId = id;
}
public void setVoiceId(long id)
{
this.voiceId = id;
}
public void setRoleId(long id)
{
this.roleId = id;
}
public void setVolume(int volume)
{
this.volume = volume;
}
public void setDefaultPlaylist(String defaultPlaylist)
{
this.defaultPlaylist = defaultPlaylist;
}
}
@@ -1,118 +1,177 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.audio;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
import java.util.HashSet;
import java.util.Set;
import me.jagrosh.jmusicbot.queue.FairQueue;
import net.dv8tion.jda.core.audio.AudioSendHandler;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.User;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class AudioHandler extends AudioEventAdapter implements AudioSendHandler {
private final AudioPlayer audioPlayer;
private final Guild guild;
private final FairQueue<QueuedTrack> queue;
private final Set<String> votes;
private AudioFrame lastFrame;
private QueuedTrack current;
public AudioHandler(AudioPlayer audioPlayer, Guild guild) {
this.audioPlayer = audioPlayer;
this.guild = guild;
queue = new FairQueue<>();
votes = new HashSet<>();
}
public int addTrack(AudioTrack track, User user)
{
QueuedTrack qt = new QueuedTrack(track, user.getId());
if(current==null)
{
current = qt;
audioPlayer.playTrack(track);
return -1;
}
else
{
return queue.add(qt);
}
}
public QueuedTrack getCurrentTrack()
{
return current;
}
public FairQueue<QueuedTrack> getQueue()
{
return queue;
}
public Set<String> getVotes()
{
return votes;
}
public AudioPlayer getPlayer()
{
return audioPlayer;
}
@Override
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
if(queue.isEmpty())
{
current = null;
guild.getAudioManager().closeAudioConnection();
}
else
{
current = queue.pull();
player.playTrack(current.getTrack());
}
}
@Override
public void onTrackStart(AudioPlayer player, AudioTrack track) {
votes.clear();
}
@Override
public boolean canProvide() {
lastFrame = audioPlayer.provide();
return lastFrame != null;
}
@Override
public byte[] provide20MsAudio() {
return lastFrame.data;
}
@Override
public boolean isOpus() {
return true;
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.audio;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.playlist.Playlist;
import com.jagrosh.jmusicbot.queue.FairQueue;
import net.dv8tion.jda.core.audio.AudioSendHandler;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.User;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class AudioHandler extends AudioEventAdapter implements AudioSendHandler {
private final AudioPlayer audioPlayer;
private final Guild guild;
private final FairQueue<QueuedTrack> queue;
private final Set<String> votes;
private final List<AudioTrack> defaultQueue;
private final Bot bot;
private AudioFrame lastFrame;
private QueuedTrack current;
public static boolean STAY_IN_CHANNEL;
public AudioHandler(AudioPlayer audioPlayer, Guild guild, Bot bot) {
this.audioPlayer = audioPlayer;
this.guild = guild;
this.bot = bot;
queue = new FairQueue<>();
votes = new HashSet<>();
defaultQueue = new LinkedList<>();
}
public int addTrack(AudioTrack track, User user)
{
QueuedTrack qt = new QueuedTrack(track, user.getId());
if(current==null)
{
current = qt;
audioPlayer.playTrack(track);
return -1;
}
else
{
return queue.add(qt);
}
}
public QueuedTrack getCurrentTrack()
{
return current;
}
public FairQueue<QueuedTrack> getQueue()
{
return queue;
}
public void stopAndClear()
{
queue.clear();
defaultQueue.clear();
audioPlayer.stopTrack();
//current = null;
}
public boolean isMusicPlaying()
{
return guild.getSelfMember().getVoiceState().inVoiceChannel() && current!=null;
}
public Set<String> getVotes()
{
return votes;
}
public AudioPlayer getPlayer()
{
return audioPlayer;
}
public boolean playFromDefault()
{
if(!defaultQueue.isEmpty())
{
current = new QueuedTrack(defaultQueue.remove(0), null);
audioPlayer.playTrack(current.getTrack());
return true;
}
if(bot.getSettings(guild)==null || bot.getSettings(guild).getDefaultPlaylist()==null)
return false;
Playlist pl = Playlist.loadPlaylist(bot.getSettings(guild).getDefaultPlaylist());
if(pl==null || pl.getItems().isEmpty())
return false;
pl.loadTracks(bot.getAudioManager(), (at) -> {
if(current==null)
{
current = new QueuedTrack(at, null);
audioPlayer.playTrack(at);
}
else
defaultQueue.add(at);
}, () -> {
if(pl.getTracks().isEmpty())
{
current = null;
if(!STAY_IN_CHANNEL)
guild.getAudioManager().closeAudioConnection();
}
});
return true;
}
@Override
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
if(queue.isEmpty())
{
current = null;
if(!playFromDefault())
{
current = null;
if(!STAY_IN_CHANNEL)
guild.getAudioManager().closeAudioConnection();
}
}
else
{
current = queue.pull();
player.playTrack(current.getTrack());
}
}
@Override
public void onTrackStart(AudioPlayer player, AudioTrack track) {
votes.clear();
}
@Override
public boolean canProvide() {
lastFrame = audioPlayer.provide();
return lastFrame != null;
}
@Override
public byte[] provide20MsAudio() {
return lastFrame.data;
}
@Override
public boolean isOpus() {
return true;
}
}
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.audio;
package com.jagrosh.jmusicbot.audio;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import me.jagrosh.jmusicbot.queue.Queueable;
import me.jagrosh.jmusicbot.utils.FormatUtil;
import com.jagrosh.jmusicbot.queue.Queueable;
import com.jagrosh.jmusicbot.utils.FormatUtil;
/**
*
@@ -1,48 +1,53 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.audio.AudioHandler;
import net.dv8tion.jda.core.entities.User;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class ForceskipCmd extends MusicCommand {
public ForceskipCmd(Bot bot)
{
super(bot);
this.name = "forceskip";
this.help = "skips the current song";
this.aliases = new String[]{"modskip"};
this.bePlaying = true;
this.category = bot.DJ;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
User u = event.getJDA().getUserById(handler.getCurrentTrack().getIdentifier());
event.reply(event.getClient().getSuccess()+" Skipped **"+handler.getCurrentTrack().getTrack().getInfo().title
+"** (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")");
handler.getPlayer().stopTrack();
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import net.dv8tion.jda.core.entities.User;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class ForceskipCmd extends MusicCommand {
public ForceskipCmd(Bot bot)
{
super(bot);
this.name = "forceskip";
this.help = "skips the current song";
this.aliases = new String[]{"modskip"};
this.bePlaying = true;
this.category = bot.DJ;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
User u;
try {
u = event.getJDA().getUserById(handler.getCurrentTrack().getIdentifier());
} catch(Exception e) {
u = null;
}
event.reply(event.getClient().getSuccess()+" Skipped **"+handler.getCurrentTrack().getTrack().getInfo().title
+"** (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")");
handler.getPlayer().stopTrack();
}
}
@@ -1,84 +1,89 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.Command;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.Settings;
import me.jagrosh.jmusicbot.audio.AudioHandler;
import net.dv8tion.jda.core.entities.GuildVoiceState;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.VoiceChannel;
import net.dv8tion.jda.core.exceptions.PermissionException;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public abstract class MusicCommand extends Command {
protected final Bot bot;
protected boolean bePlaying;
protected boolean beListening;
public MusicCommand(Bot bot)
{
this.bot = bot;
this.guildOnly = true;
this.category = bot.MUSIC;
}
@Override
protected void execute(CommandEvent event) {
Settings settings = bot.getSettings(event.getGuild());
TextChannel tchannel = event.getGuild().getTextChannelById(settings.getTextId());
if(tchannel!=null && !event.getTextChannel().equals(tchannel))
{
try {
event.getMessage().deleteMessage().queue();
} catch(PermissionException e){}
event.replyInDM(event.getClient().getError()+" You can only use that command in <#"+settings.getTextId()+">!");
return;
}
if(bePlaying
&& (event.getGuild().getAudioManager().getSendingHandler()==null
|| ((AudioHandler)event.getGuild().getAudioManager().getSendingHandler()).getCurrentTrack()==null))
{
event.reply(event.getClient().getError()+" There must be music playing to use that!");
return;
}
if(beListening)
{
VoiceChannel current = event.getGuild().getSelfMember().getVoiceState().getChannel();
if(current==null)
current = event.getGuild().getVoiceChannelById(settings.getVoiceId());
GuildVoiceState userState = event.getMember().getVoiceState();
if(!userState.inVoiceChannel() || userState.isDeafened() || (current!=null && !userState.getChannel().equals(current)))
{
event.reply(event.getClient().getError()
+" You must be listening in "+(current==null ? "a voice channel" : "**"+current.getName()+"**")
+" to use that!");
return;
}
if(!event.getGuild().getSelfMember().getVoiceState().inVoiceChannel())
event.getGuild().getAudioManager().openAudioConnection(userState.getChannel());
}
doCommand(event);
}
public abstract void doCommand(CommandEvent event);
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.Settings;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import net.dv8tion.jda.core.entities.GuildVoiceState;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.VoiceChannel;
import net.dv8tion.jda.core.exceptions.PermissionException;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public abstract class MusicCommand extends Command {
protected final Bot bot;
protected boolean bePlaying;
protected boolean beListening;
public MusicCommand(Bot bot)
{
this.bot = bot;
this.guildOnly = true;
this.category = bot.MUSIC;
}
@Override
protected void execute(CommandEvent event) {
Settings settings = bot.getSettings(event.getGuild());
TextChannel tchannel = event.getGuild().getTextChannelById(settings.getTextId());
if(tchannel!=null && !event.getTextChannel().equals(tchannel))
{
try {
event.getMessage().delete().queue();
} catch(PermissionException e){}
event.replyInDM(event.getClient().getError()+" You can only use that command in <#"+settings.getTextId()+">!");
return;
}
if(bePlaying
&& (event.getGuild().getAudioManager().getSendingHandler()==null
|| !((AudioHandler)event.getGuild().getAudioManager().getSendingHandler()).isMusicPlaying()))
{
event.reply(event.getClient().getError()+" There must be music playing to use that!");
return;
}
if(beListening)
{
VoiceChannel current = event.getGuild().getSelfMember().getVoiceState().getChannel();
if(current==null)
current = event.getGuild().getVoiceChannelById(settings.getVoiceId());
GuildVoiceState userState = event.getMember().getVoiceState();
if(!userState.inVoiceChannel() || userState.isDeafened() || (current!=null && !userState.getChannel().equals(current)))
{
event.reply(event.getClient().getError()
+" You must be listening in "+(current==null ? "a voice channel" : "**"+current.getName()+"**")
+" to use that!");
return;
}
if(!event.getGuild().getSelfMember().getVoiceState().inVoiceChannel())
try {
event.getGuild().getAudioManager().openAudioConnection(userState.getChannel());
}catch(PermissionException ex) {
event.reply(event.getClient().getError()+" I am unable to connect to **"+userState.getChannel().getName()+"**!");
return;
}
}
doCommand(event);
}
public abstract void doCommand(CommandEvent event);
}
@@ -0,0 +1,85 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioTrack;
import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioTrack;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.User;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class NowplayingCmd extends MusicCommand {
public NowplayingCmd(Bot bot)
{
super(bot);
this.name = "nowplaying";
this.help = "shows the song that is currently playing";
this.aliases = new String[]{"np","current"};
this.botPermissions = new Permission[]{Permission.MESSAGE_EMBED_LINKS};
}
@Override
public void doCommand(CommandEvent event) {
EmbedBuilder eb = new EmbedBuilder();
eb.setColor(event.getSelfMember().getColor());
AudioHandler ah = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
if(ah==null || !ah.isMusicPlaying())
{
eb.setTitle("No music playing");
eb.setDescription("\u23F9 "+FormatUtil.progressBar(-1)+" "+FormatUtil.volumeIcon(ah==null?100:ah.getPlayer().getVolume()));
event.reply(eb.build());
return;
}
if(ah.getCurrentTrack().getIdentifier()!=null)
{
User u;
try {
u = event.getJDA().getUserById(ah.getCurrentTrack().getIdentifier());
} catch(Exception e) {
u = null;
}
if(u==null)
eb.setAuthor("Unknown (ID:"+ah.getCurrentTrack().getIdentifier()+")", null, null);
else
eb.setAuthor(u.getName()+"#"+u.getDiscriminator(), null, u.getEffectiveAvatarUrl());
}
try {
eb.setTitle(ah.getCurrentTrack().getTrack().getInfo().title, ah.getCurrentTrack().getTrack().getInfo().uri);
} catch(Exception e) {
eb.setTitle(ah.getCurrentTrack().getTrack().getInfo().title);
}
if(ah.getCurrentTrack().getTrack() instanceof YoutubeAudioTrack)
eb.setThumbnail("https://img.youtube.com/vi/"+ah.getCurrentTrack().getTrack().getIdentifier()+"/maxresdefault.jpg");
eb.setDescription(FormatUtil.embedformattedAudio(ah));
event.reply(eb.build());
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import net.dv8tion.jda.core.entities.User;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class PauseCmd extends MusicCommand {
public PauseCmd(Bot bot)
{
super(bot);
this.name = "pause";
this.help = "pauses the current song";
this.bePlaying = true;
this.category = bot.DJ;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
if(handler.getPlayer().isPaused())
{
event.replyWarning("The player is already paused! Use `"+event.getClient().getPrefix()+"play` to unpause!");
return;
}
handler.getPlayer().setPaused(true);
event.replySuccess("Paused **"+handler.getCurrentTrack().getTrack().getInfo().title+"**. Type `"+event.getClient().getPrefix()+"play` to unpause!");
}
}
@@ -1,115 +1,183 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException.Severity;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.entities.Message;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class PlayCmd extends MusicCommand {
public PlayCmd(Bot bot)
{
super(bot);
this.name = "play";
this.arguments = "<title|URL>";
this.help = "plays the provided song";
this.beListening = true;
this.bePlaying = false;
}
@Override
public void doCommand(CommandEvent event) {
if(event.getArgs().isEmpty())
{
event.reply(event.getClient().getError()+" Please include a url or song title.");
return;
}
String args = event.getArgs().startsWith("<") && event.getArgs().endsWith(">")
? event.getArgs().substring(1,event.getArgs().length()-1)
: event.getArgs();
event.getChannel().sendMessage("\u231A Loading... `["+args+"]`").queue(m -> {
bot.getAudioManager().loadItemOrdered(event.getGuild(), args, new ResultHandler(m,event,false));
});
}
private class ResultHandler implements AudioLoadResultHandler {
final Message m;
final CommandEvent event;
final boolean ytsearch;
private ResultHandler(Message m, CommandEvent event, boolean ytsearch)
{
this.m = m;
this.event = event;
this.ytsearch = ytsearch;
}
@Override
public void trackLoaded(AudioTrack track) {
int pos = bot.queueTrack(event, track)+1;
m.editMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
: " to the queue at position "+pos)).queue();
}
@Override
public void playlistLoaded(AudioPlaylist playlist) {
if(playlist.getTracks().size()==1 || playlist.isSearchResult() || playlist.getSelectedTrack()!=null)
{
AudioTrack single = playlist.getSelectedTrack()==null?playlist.getTracks().get(0):playlist.getSelectedTrack();
int pos = bot.queueTrack(event, single)+1;
m.editMessage(event.getClient().getSuccess()+" Added **"+single.getInfo().title
+"** (`"+FormatUtil.formatTime(single.getDuration())+"`) "+(pos==0 ? "to begin playing"
: " to the queue at position "+pos)).queue();
}
else
{
m.editMessage(event.getClient().getSuccess()+" Found "
+(playlist.getName()==null?"a playlist":"playlist **"+playlist.getName()+"**")+" with `"
+playlist.getTracks().size()+"` entries; adding to the queue.").queue();
playlist.getTracks().stream().forEach((track) -> {
bot.queueTrack(event, track);
});
}
}
@Override
public void noMatches() {
if(ytsearch)
m.editMessage(event.getClient().getWarning()+" No results found for `"+event.getArgs()+"`.").queue();
else
bot.getAudioManager().loadItemOrdered(event.getGuild(), "ytsearch:"+event.getArgs(), new ResultHandler(m,event,true));
}
@Override
public void loadFailed(FriendlyException throwable) {
if(throwable.severity==Severity.COMMON)
m.editMessage(event.getClient().getError()+" Error loading: "+throwable.getMessage()).queue();
else
m.editMessage(event.getClient().getError()+" Error loading track.").queue();
}
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException.Severity;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.playlist.Playlist;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Message;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class PlayCmd extends MusicCommand {
public PlayCmd(Bot bot)
{
super(bot);
this.name = "play";
this.arguments = "<title|URL|subcommand>";
this.help = "plays the provided song";
this.beListening = true;
this.bePlaying = false;
this.children = new Command[]{new PlaylistCmd(bot)};
}
@Override
public void doCommand(CommandEvent event) {
if(event.getArgs().isEmpty())
{
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
if(handler!=null && handler.getCurrentTrack()!=null && handler.getPlayer().isPaused())
{
boolean isDJ = event.getMember().hasPermission(Permission.MANAGE_SERVER);
if(!isDJ)
isDJ = event.getMember().getRoles().contains(event.getGuild().getRoleById(bot.getSettings(event.getGuild()).getRoleId()));
if(!isDJ)
event.replyError("Only DJs can unpause the player!");
else
{
handler.getPlayer().setPaused(false);
event.replySuccess("Resumed **"+handler.getCurrentTrack().getTrack().getInfo().title+"**.");
}
return;
}
StringBuilder builder = new StringBuilder(event.getClient().getWarning()+" Play Commands:\n");
builder.append("\n`").append(event.getClient().getPrefix()).append(name).append(" <song title>` - plays the first result from Youtube");
builder.append("\n`").append(event.getClient().getPrefix()).append(name).append(" <URL>` - plays the provided song, playlist, or stream");
for(Command cmd: children)
builder.append("\n`").append(event.getClient().getPrefix()).append(name).append(" ").append(cmd.getName()).append(" ").append(cmd.getArguments()).append("` - ").append(cmd.getHelp());
event.reply(builder.toString());
return;
}
String args = event.getArgs().startsWith("<") && event.getArgs().endsWith(">")
? event.getArgs().substring(1,event.getArgs().length()-1)
: event.getArgs();
event.getChannel().sendMessage("\u231A Loading... `["+args+"]`").queue(m -> {
bot.getAudioManager().loadItemOrdered(event.getGuild(), args, new ResultHandler(m,event,false));
});
}
private class ResultHandler implements AudioLoadResultHandler {
final Message m;
final CommandEvent event;
final boolean ytsearch;
private ResultHandler(Message m, CommandEvent event, boolean ytsearch)
{
this.m = m;
this.event = event;
this.ytsearch = ytsearch;
}
@Override
public void trackLoaded(AudioTrack track) {
int pos = bot.queueTrack(event, track)+1;
m.editMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
: " to the queue at position "+pos)).queue();
}
@Override
public void playlistLoaded(AudioPlaylist playlist) {
if(playlist.getTracks().size()==1 || playlist.isSearchResult() || playlist.getSelectedTrack()!=null)
{
AudioTrack single = playlist.getSelectedTrack()==null?playlist.getTracks().get(0):playlist.getSelectedTrack();
int pos = bot.queueTrack(event, single)+1;
m.editMessage(event.getClient().getSuccess()+" Added **"+single.getInfo().title
+"** (`"+FormatUtil.formatTime(single.getDuration())+"`) "+(pos==0 ? "to begin playing"
: " to the queue at position "+pos)).queue();
}
else
{
m.editMessage(event.getClient().getSuccess()+" Found "
+(playlist.getName()==null?"a playlist":"playlist **"+playlist.getName()+"**")+" with `"
+playlist.getTracks().size()+"` entries; added to the queue!").queue();
playlist.getTracks().stream().forEach((track) -> {
bot.queueTrack(event, track);
});
}
}
@Override
public void noMatches() {
if(ytsearch)
m.editMessage(event.getClient().getWarning()+" No results found for `"+event.getArgs()+"`.").queue();
else
bot.getAudioManager().loadItemOrdered(event.getGuild(), "ytsearch:"+event.getArgs(), new ResultHandler(m,event,true));
}
@Override
public void loadFailed(FriendlyException throwable) {
if(throwable.severity==Severity.COMMON)
m.editMessage(event.getClient().getError()+" Error loading: "+throwable.getMessage()).queue();
else
m.editMessage(event.getClient().getError()+" Error loading track.").queue();
}
}
public class PlaylistCmd extends MusicCommand {
public PlaylistCmd(Bot bot)
{
super(bot);
this.name = "playlist";
this.aliases = new String[]{"pl"};
this.arguments = "<name>";
this.help = "plays the provided playlist";
this.beListening = true;
this.bePlaying = false;
}
@Override
public void doCommand(CommandEvent event) {
if(event.getArgs().isEmpty())
{
event.reply(event.getClient().getError()+" Please include a playlist name.");
return;
}
Playlist playlist = Playlist.loadPlaylist(event.getArgs());
if(playlist==null)
{
event.reply(event.getClient().getError()+" I could not find `"+event.getArgs()+".txt` in the Playlists folder.");
return;
}
event.getChannel().sendMessage("\u231A Loading playlist **"+event.getArgs()+"**... ("+playlist.getItems().size()+" items)").queue(m -> {
playlist.loadTracks(bot.getAudioManager(), (at)->bot.queueTrack(event, at), () -> {
StringBuilder builder = new StringBuilder(playlist.getTracks().isEmpty()
? event.getClient().getWarning()+" No tracks were loaded!"
: event.getClient().getSuccess()+" Loaded **"+playlist.getTracks().size()+"** tracks!");
if(!playlist.getErrors().isEmpty())
builder.append("\nThe following tracks failed to load:");
playlist.getErrors().forEach(err -> builder.append("\n`[").append(err.getIndex()+1).append("]` **").append(err.getItem()).append("**: ").append(err.getReason()));
String str = builder.toString();
if(str.length()>2000)
str = str.substring(0,1994)+" (...)";
m.editMessage(str).queue();
});
});
}
}
}
@@ -0,0 +1,250 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.playlist.Playlist;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class PlaylistCmd extends Command {
private final Bot bot;
public PlaylistCmd(Bot bot)
{
this.bot = bot;
this.category = bot.OWNER;
this.ownerCommand = true;
this.guildOnly = false;
this.name = "playlist";
this.arguments = "<append|delete|make|setdefault>";
this.help = "playlist management";
this.children = new Command[]{
new ListCmd(),
new AppendlistCmd(),
new DeletelistCmd(),
new MakelistCmd(),
new DefaultlistCmd()
};
}
@Override
public void execute(CommandEvent event) {
StringBuilder builder = new StringBuilder(event.getClient().getWarning()+" Playlist Management Commands:\n");
for(Command cmd: this.children)
builder.append("\n`").append(event.getClient().getPrefix()).append(name).append(" ").append(cmd.getName())
.append(" ").append(cmd.getArguments()==null ? "" : cmd.getArguments()).append("` - ").append(cmd.getHelp());
event.reply(builder.toString());
}
public class MakelistCmd extends Command {
public MakelistCmd()
{
this.name = "make";
this.aliases = new String[]{"create"};
this.help = "makes a new playlist";
this.arguments = "<name>";
this.category = bot.OWNER;
this.ownerCommand = true;
this.guildOnly = false;
}
@Override
protected void execute(CommandEvent event) {
String pname = event.getArgs().replaceAll("\\s+", "_");
if(Playlist.loadPlaylist(pname)==null)
{
try
{
Files.createFile(Paths.get("Playlists"+File.separator+pname+".txt"));
event.reply(event.getClient().getSuccess()+" Successfully created playlist `"+pname+"`!");
}
catch(IOException e)
{
event.reply(event.getClient().getError()+" I was unable to create the playlist: "+e.getLocalizedMessage());
}
}
else
event.reply(event.getClient().getError()+" Playlist `"+pname+"` already exists!");
}
}
public class DeletelistCmd extends Command {
public DeletelistCmd()
{
this.name = "delete";
this.aliases = new String[]{"remove"};
this.help = "deletes an existing playlist";
this.arguments = "<name>";
this.guildOnly = false;
this.ownerCommand = true;
this.category = bot.OWNER;
}
@Override
protected void execute(CommandEvent event) {
String pname = event.getArgs().replaceAll("\\s+", "_");
if(Playlist.loadPlaylist(pname)==null)
event.reply(event.getClient().getError()+" Playlist `"+pname+"` doesn't exist!");
else
{
try
{
Files.delete(Paths.get("Playlists"+File.separator+pname+".txt"));
event.reply(event.getClient().getSuccess()+" Successfully deleted playlist `"+pname+"`!");
}
catch(IOException e)
{
event.reply(event.getClient().getError()+" I was unable to delete the playlist: "+e.getLocalizedMessage());
}
}
}
}
public class AppendlistCmd extends Command {
public AppendlistCmd()
{
this.name = "append";
this.aliases = new String[]{"add"};
this.help = "appends songs to an existing playlist";
this.arguments = "<name> <URL> | <URL> | ...";
this.guildOnly = false;
this.ownerCommand = true;
this.category = bot.OWNER;
}
@Override
protected void execute(CommandEvent event) {
String[] parts = event.getArgs().split("\\s+", 2);
if(parts.length<2)
{
event.reply(event.getClient().getError()+" Please include a playlist name and URLs to add!");
return;
}
String pname = parts[0];
Playlist playlist = Playlist.loadPlaylist(pname);
if(playlist==null)
event.reply(event.getClient().getError()+" Playlist `"+pname+"` doesn't exist!");
else
{
StringBuilder builder = new StringBuilder();
playlist.getItems().forEach(item -> builder.append("\r\n").append(item));
String[] urls = parts[1].split("\\|");
for(String url: urls)
{
String u = url.trim();
if(u.startsWith("<") && u.endsWith(">"))
u = u.substring(1, u.length()-1);
builder.append("\r\n").append(u);
}
try
{
Files.write(Paths.get("Playlists"+File.separator+pname+".txt"), builder.toString().trim().getBytes());
event.reply(event.getClient().getSuccess()+" Successfully added "+urls.length+" songs to playlist `"+pname+"`!");
}
catch(IOException e)
{
event.reply(event.getClient().getError()+" I was unable to append to the playlist: "+e.getLocalizedMessage());
}
}
}
}
public class DefaultlistCmd extends Command {
public DefaultlistCmd()
{
this.name = "setdefault";
this.aliases = new String[]{"default"};
this.help = "sets the default playlist for the server";
this.arguments = "<playlistname|NONE>";
this.guildOnly = true;
this.ownerCommand = true;
this.category = bot.OWNER;
}
@Override
protected void execute(CommandEvent event) {
if(event.getArgs().isEmpty())
{
event.reply(event.getClient().getError()+" Please include a playlist name or NONE");
}
if(event.getArgs().equalsIgnoreCase("none"))
{
bot.setDefaultPlaylist(event.getGuild(), null);
event.reply(event.getClient().getSuccess()+" Cleared the default playlist for **"+event.getGuild().getName()+"**");
return;
}
String pname = event.getArgs().replaceAll("\\s+", "_");
if(Playlist.loadPlaylist(pname)==null)
{
event.reply(event.getClient().getError()+" Could not find `"+pname+".txt`!");
}
else
{
bot.setDefaultPlaylist(event.getGuild(), pname);
event.reply(event.getClient().getSuccess()+" The default playlist for **"+event.getGuild().getName()+"** is now `"+pname+"`");
}
}
}
public class ListCmd extends Command {
public ListCmd()
{
this.name = "all";
this.aliases = new String[]{"available","list"};
this.help = "lists all available playlists";
this.guildOnly = true;
this.ownerCommand = true;
this.category = bot.OWNER;
}
@Override
protected void execute(CommandEvent event) {
if(!Playlist.folderExists())
Playlist.createFolder();
if(!Playlist.folderExists())
{
event.reply(event.getClient().getWarning()+" Playlists folder does not exist and could not be created!");
return;
}
List<String> list = Playlist.getPlaylists();
if(list==null)
event.reply(event.getClient().getError()+" Failed to load available playlists!");
else if(list.isEmpty())
event.reply(event.getClient().getWarning()+" There are no playlists in the Playlists folder!");
else
{
StringBuilder builder = new StringBuilder(event.getClient().getSuccess()+" Available playlists:\n");
list.forEach(str -> builder.append("`").append(str).append("` "));
event.reply(builder.toString());
}
}
}
}
@@ -0,0 +1,63 @@
/*
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import java.util.List;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.playlist.Playlist;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class PlaylistsCmd extends MusicCommand {
public PlaylistsCmd(Bot bot)
{
super(bot);
this.name = "playlists";
this.help = "shows the available playlists";
this.aliases = new String[]{"pls"};
this.guildOnly = true;
this.beListening = false;
this.beListening = false;
}
@Override
public void doCommand(CommandEvent event) {
if(!Playlist.folderExists())
Playlist.createFolder();
if(!Playlist.folderExists())
{
event.reply(event.getClient().getWarning()+" Playlists folder does not exist and could not be created!");
return;
}
List<String> list = Playlist.getPlaylists();
if(list==null)
event.reply(event.getClient().getError()+" Failed to load available playlists!");
else if(list.isEmpty())
event.reply(event.getClient().getWarning()+" There are no playlists in the Playlists folder!");
else
{
StringBuilder builder = new StringBuilder(event.getClient().getSuccess()+" Available playlists:\n");
list.forEach(str -> builder.append("`").append(str).append("` "));
builder.append("\nType `").append(event.getClient().getTextualPrefix()).append("play playlist <name>` to play a playlist");
event.reply(builder.toString());
}
}
}
@@ -1,84 +1,94 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import java.util.List;
import java.util.concurrent.TimeUnit;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jdautilities.menu.pagination.PaginatorBuilder;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.audio.AudioHandler;
import me.jagrosh.jmusicbot.audio.QueuedTrack;
import me.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.exceptions.PermissionException;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class QueueCmd extends MusicCommand {
private final PaginatorBuilder builder;
public QueueCmd(Bot bot)
{
super(bot);
this.name = "queue";
this.help = "shows the current queue";
this.arguments = "[pagenum]";
this.aliases = new String[]{"list"};
this.bePlaying = true;
this.botPermissions = new Permission[]{Permission.MESSAGE_ADD_REACTION,Permission.MESSAGE_EMBED_LINKS};
builder = new PaginatorBuilder()
.setColumns(1)
.setFinalAction(m -> {try{m.clearReactions().queue();}catch(PermissionException e){}})
.setItemsPerPage(10)
.waitOnSinglePage(false)
.useNumberedItems(true)
.showPageNumbers(true)
.setEventWaiter(bot.getWaiter())
.setTimeout(1, TimeUnit.MINUTES)
;
}
@Override
public void doCommand(CommandEvent event) {
int pagenum = 1;
try{
pagenum = Integer.parseInt(event.getArgs());
}catch(NumberFormatException e){}
List<QueuedTrack> list = ((AudioHandler)event.getGuild().getAudioManager().getSendingHandler()).getQueue().getList();
if(list.isEmpty())
{
event.reply(event.getClient().getWarning()+" There is no music in the queue!");
return;
}
String[] songs = new String[list.size()];
long total = 0;
for(int i=0; i<list.size(); i++)
{
total += list.get(i).getTrack().getDuration();
songs[i] = list.get(i).toString();
}
builder.setText(event.getClient().getSuccess()+" Current Queue | "+songs.length+" entries | `"+FormatUtil.formatTime(total)+"` ")
.setItems(songs)
.setUsers(event.getAuthor())
.setColor(event.getSelfMember().getColor())
;
builder.build().paginate(event.getChannel(), pagenum);
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import java.util.List;
import java.util.concurrent.TimeUnit;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jdautilities.menu.pagination.PaginatorBuilder;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.audio.QueuedTrack;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.exceptions.PermissionException;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class QueueCmd extends MusicCommand {
private final PaginatorBuilder builder;
public QueueCmd(Bot bot)
{
super(bot);
this.name = "queue";
this.help = "shows the current queue";
this.arguments = "[pagenum]";
this.aliases = new String[]{"list"};
this.bePlaying = true;
this.botPermissions = new Permission[]{Permission.MESSAGE_ADD_REACTION,Permission.MESSAGE_EMBED_LINKS};
builder = new PaginatorBuilder()
.setColumns(1)
.setFinalAction(m -> {try{m.clearReactions().queue();}catch(PermissionException e){}})
.setItemsPerPage(10)
.waitOnSinglePage(false)
.useNumberedItems(true)
.showPageNumbers(true)
.setEventWaiter(bot.getWaiter())
.setTimeout(1, TimeUnit.MINUTES)
;
}
@Override
public void doCommand(CommandEvent event) {
int pagenum = 1;
try{
pagenum = Integer.parseInt(event.getArgs());
}catch(NumberFormatException e){}
AudioHandler ah = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
List<QueuedTrack> list = ah.getQueue().getList();
if(list.isEmpty())
{
event.replyWarning("There is no music in the queue!"
+(!ah.isMusicPlaying() ? "" : " Now playing:\n\n**"+ah.getCurrentTrack().getTrack().getInfo().title+"**\n"+FormatUtil.embedformattedAudio(ah)));
return;
}
String[] songs = new String[list.size()];
long total = 0;
for(int i=0; i<list.size(); i++)
{
total += list.get(i).getTrack().getDuration();
songs[i] = list.get(i).toString();
}
long fintotal = total;
builder.setText((i1,i2) -> getQueueTitle(ah, event.getClient().getSuccess(), songs.length, fintotal))
.setItems(songs)
.setUsers(event.getAuthor())
.setColor(event.getSelfMember().getColor())
;
builder.build().paginate(event.getChannel(), pagenum);
}
private String getQueueTitle(AudioHandler ah, String success, int songslength, long total)
{
StringBuilder sb = new StringBuilder();
if(ah.getCurrentTrack()!=null)
sb.append("**").append(ah.getCurrentTrack().getTrack().getInfo().title).append("**\n").append(FormatUtil.embedformattedAudio(ah)).append("\n\n");
return sb.append(success).append(" Current Queue | ").append(songslength).append(" entries | `").append(FormatUtil.formatTime(total)).append("` ").toString();
}
}
@@ -1,85 +1,98 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.audio.AudioHandler;
import me.jagrosh.jmusicbot.audio.QueuedTrack;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.entities.User;
import net.dv8tion.jda.core.utils.PermissionUtil;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class RemoveCmd extends MusicCommand {
public RemoveCmd(Bot bot)
{
super(bot);
this.name = "remove";
this.help = "removes a song from the queue";
this.arguments = "<position>";
this.aliases = new String[]{"delete"};
this.beListening = true;
this.bePlaying = true;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
if(handler.getQueue().isEmpty())
{
event.reply(event.getClient().getError()+" There is nothing in the queue!");
return;
}
int pos;
try {
pos = Integer.parseInt(event.getArgs());
} catch(NumberFormatException e) {
pos = 0;
}
if(pos<1 || pos>handler.getQueue().size())
{
event.reply(event.getClient().getError()+" Position must be a valid integer between 1 and "+handler.getQueue().size()+"!");
return;
}
boolean isDJ = PermissionUtil.checkPermission(event.getGuild(), event.getMember(), Permission.MANAGE_SERVER);
if(!isDJ)
isDJ = event.getMember().getRoles().contains(event.getGuild().getRoleById(bot.getSettings(event.getGuild()).getRoleId()));
QueuedTrack qt = handler.getQueue().get(pos-1);
if(qt.getIdentifier().equals(event.getAuthor().getId()))
{
handler.getQueue().remove(pos-1);
event.reply(event.getClient().getSuccess()+" Removed **"+qt.getTrack().getInfo().title+"** from the queue");
}
else if(isDJ)
{
handler.getQueue().remove(pos-1);
User u = event.getJDA().getUserById(qt.getIdentifier());
event.reply(event.getClient().getSuccess()+" Removed **"+qt.getTrack().getInfo().title
+"** from the queue (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")");
}
else
{
event.reply(event.getClient().getError()+" You cannot remove **"+qt.getTrack().getInfo().title+"** because you didn't add it!");
}
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.audio.QueuedTrack;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.User;
import net.dv8tion.jda.core.utils.PermissionUtil;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class RemoveCmd extends MusicCommand {
public RemoveCmd(Bot bot)
{
super(bot);
this.name = "remove";
this.help = "removes a song from the queue";
this.arguments = "<position|ALL>";
this.aliases = new String[]{"delete"};
this.beListening = true;
this.bePlaying = true;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
if(handler.getQueue().isEmpty())
{
event.reply(event.getClient().getError()+" There is nothing in the queue!");
return;
}
if(event.getArgs().equalsIgnoreCase("all"))
{
int count = handler.getQueue().removeAll(event.getAuthor().getId());
if(count==0)
event.reply(event.getClient().getWarning()+" You don't have any songs in the queue!");
else
event.reply(event.getClient().getSuccess()+" Successfully removed your "+count+" entries.");
return;
}
int pos;
try {
pos = Integer.parseInt(event.getArgs());
} catch(NumberFormatException e) {
pos = 0;
}
if(pos<1 || pos>handler.getQueue().size())
{
event.reply(event.getClient().getError()+" Position must be a valid integer between 1 and "+handler.getQueue().size()+"!");
return;
}
boolean isDJ = event.getMember().hasPermission(Permission.MANAGE_SERVER);
if(!isDJ)
isDJ = event.getMember().getRoles().contains(event.getGuild().getRoleById(bot.getSettings(event.getGuild()).getRoleId()));
QueuedTrack qt = handler.getQueue().get(pos-1);
if(qt.getIdentifier().equals(event.getAuthor().getId()))
{
handler.getQueue().remove(pos-1);
event.reply(event.getClient().getSuccess()+" Removed **"+qt.getTrack().getInfo().title+"** from the queue");
}
else if(isDJ)
{
handler.getQueue().remove(pos-1);
User u;
try {
u = event.getJDA().getUserById(qt.getIdentifier());
} catch(Exception e) {
u = null;
}
event.reply(event.getClient().getSuccess()+" Removed **"+qt.getTrack().getInfo().title
+"** from the queue (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")");
}
else
{
event.reply(event.getClient().getError()+" You cannot remove **"+qt.getTrack().getInfo().title+"** because you didn't add it!");
}
}
}
@@ -0,0 +1,121 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException.Severity;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import java.util.concurrent.TimeUnit;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jdautilities.menu.orderedmenu.OrderedMenuBuilder;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Message;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SCSearchCmd extends MusicCommand {
private final OrderedMenuBuilder builder;
public SCSearchCmd(Bot bot)
{
super(bot);
this.name = "scsearch";
this.arguments = "<query>";
this.help = "searches Soundcloud for a provided query";
this.beListening = true;
this.bePlaying = false;
this.botPermissions = new Permission[]{Permission.MESSAGE_EMBED_LINKS};
builder = new OrderedMenuBuilder()
.allowTextInput(true)
.useNumbers()
.useCancelButton(true)
.setEventWaiter(bot.getWaiter())
.setTimeout(1, TimeUnit.MINUTES)
;
}
@Override
public void doCommand(CommandEvent event) {
if(event.getArgs().isEmpty())
{
event.reply(event.getClient().getError()+" Please include a query.");
return;
}
event.getChannel().sendMessage("\uD83D\uDD0E Searching... `["+event.getArgs()+"]`").queue(m -> {
bot.getAudioManager().loadItemOrdered(event.getGuild(), "scsearch:"+event.getArgs(), new ResultHandler(m,event));
});
}
private class ResultHandler implements AudioLoadResultHandler {
final Message m;
final CommandEvent event;
private ResultHandler(Message m, CommandEvent event)
{
this.m = m;
this.event = event;
}
@Override
public void trackLoaded(AudioTrack track) {
int pos = bot.queueTrack(event, track)+1;
m.editMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
: " to the queue at position "+pos)).queue();
}
@Override
public void playlistLoaded(AudioPlaylist playlist) {
builder.setColor(event.getSelfMember().getColor())
.setText(event.getClient().getSuccess()+" Search results for `"+event.getArgs()+"`:")
.setChoices(new String[0])
.setAction(i -> {
AudioTrack track = playlist.getTracks().get(i-1);
int pos = bot.queueTrack(event, track)+1;
event.getChannel().sendMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
: " to the queue at position "+pos)).queue();
})
.setCancel(() -> m.delete().queue())
.setUsers(event.getAuthor())
;
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.build().display(m);
}
@Override
public void noMatches() {
m.editMessage(event.getClient().getWarning()+" No results found for `"+event.getArgs()+"`.").queue();
}
@Override
public void loadFailed(FriendlyException throwable) {
if(throwable.severity==Severity.COMMON)
m.editMessage(event.getClient().getError()+" Error loading: "+throwable.getMessage()).queue();
else
m.editMessage(event.getClient().getError()+" Error loading track.").queue();
}
}
}
@@ -1,121 +1,122 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException.Severity;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import java.util.concurrent.TimeUnit;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jdautilities.menu.orderedmenu.OrderedMenuBuilder;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Message;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SearchCmd extends MusicCommand {
private final OrderedMenuBuilder builder;
public SearchCmd(Bot bot)
{
super(bot);
this.name = "search";
this.arguments = "<query>";
this.help = "searches Youtube for a provided query";
this.beListening = true;
this.bePlaying = false;
this.botPermissions = new Permission[]{Permission.MESSAGE_EMBED_LINKS};
builder = new OrderedMenuBuilder()
.allowTextInput(true)
.useNumbers()
.useCancelButton(true)
.setEventWaiter(bot.getWaiter())
.setTimeout(1, TimeUnit.MINUTES)
;
}
@Override
public void doCommand(CommandEvent event) {
if(event.getArgs().isEmpty())
{
event.reply(event.getClient().getError()+" Please include a query.");
return;
}
event.getChannel().sendMessage("\uD83D\uDD0E Searching... `["+event.getArgs()+"]`").queue(m -> {
bot.getAudioManager().loadItemOrdered(event.getGuild(), "ytsearch:"+event.getArgs(), new ResultHandler(m,event));
});
}
private class ResultHandler implements AudioLoadResultHandler {
final Message m;
final CommandEvent event;
private ResultHandler(Message m, CommandEvent event)
{
this.m = m;
this.event = event;
}
@Override
public void trackLoaded(AudioTrack track) {
int pos = bot.queueTrack(event, track)+1;
m.editMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
: " to the queue at position "+pos)).queue();
}
@Override
public void playlistLoaded(AudioPlaylist playlist) {
builder.setColor(event.getSelfMember().getColor())
.setText(event.getClient().getSuccess()+" Search results for `"+event.getArgs()+"`:")
.setChoices(new String[0])
.setAction(i -> {
AudioTrack track = playlist.getTracks().get(i-1);
int pos = bot.queueTrack(event, track)+1;
event.getChannel().sendMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
: " to the queue at position "+pos)).queue();
})
.setUsers(event.getAuthor())
;
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+"**](https://youtu.be/"+track.getIdentifier()+")");
}
builder.build().display(m);
}
@Override
public void noMatches() {
m.editMessage(event.getClient().getWarning()+" No results found for `"+event.getArgs()+"`.").queue();
}
@Override
public void loadFailed(FriendlyException throwable) {
if(throwable.severity==Severity.COMMON)
m.editMessage(event.getClient().getError()+" Error loading: "+throwable.getMessage()).queue();
else
m.editMessage(event.getClient().getError()+" Error loading track.").queue();
}
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException.Severity;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import java.util.concurrent.TimeUnit;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jdautilities.menu.orderedmenu.OrderedMenuBuilder;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Message;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SearchCmd extends MusicCommand {
private final OrderedMenuBuilder builder;
public SearchCmd(Bot bot)
{
super(bot);
this.name = "search";
this.aliases = new String[]{"ytsearch"};
this.arguments = "<query>";
this.help = "searches Youtube for a provided query";
this.beListening = true;
this.bePlaying = false;
this.botPermissions = new Permission[]{Permission.MESSAGE_EMBED_LINKS};
builder = new OrderedMenuBuilder()
.allowTextInput(true)
.useNumbers()
.useCancelButton(true)
.setEventWaiter(bot.getWaiter())
.setTimeout(1, TimeUnit.MINUTES)
;
}
@Override
public void doCommand(CommandEvent event) {
if(event.getArgs().isEmpty())
{
event.reply(event.getClient().getError()+" Please include a query.");
return;
}
event.getChannel().sendMessage("\uD83D\uDD0E Searching... `["+event.getArgs()+"]`").queue(m -> {
bot.getAudioManager().loadItemOrdered(event.getGuild(), "ytsearch:"+event.getArgs(), new ResultHandler(m,event));
});
}
private class ResultHandler implements AudioLoadResultHandler {
final Message m;
final CommandEvent event;
private ResultHandler(Message m, CommandEvent event)
{
this.m = m;
this.event = event;
}
@Override
public void trackLoaded(AudioTrack track) {
int pos = bot.queueTrack(event, track)+1;
m.editMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
: " to the queue at position "+pos)).queue();
}
@Override
public void playlistLoaded(AudioPlaylist playlist) {
builder.setColor(event.getSelfMember().getColor())
.setText(event.getClient().getSuccess()+" Search results for `"+event.getArgs()+"`:")
.setChoices(new String[0])
.setAction(i -> {
AudioTrack track = playlist.getTracks().get(i-1);
int pos = bot.queueTrack(event, track)+1;
event.getChannel().sendMessage(event.getClient().getSuccess()+" Added **"+track.getInfo().title
+"** (`"+FormatUtil.formatTime(track.getDuration())+"`) "+(pos==0 ? "to begin playing"
: " to the queue at position "+pos)).queue();
})
.setCancel(() -> m.delete().queue())
.setUsers(event.getAuthor())
;
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+"**](https://youtu.be/"+track.getIdentifier()+")");
}
builder.build().display(m);
}
@Override
public void noMatches() {
m.editMessage(event.getClient().getWarning()+" No results found for `"+event.getArgs()+"`.").queue();
}
@Override
public void loadFailed(FriendlyException throwable) {
if(throwable.severity==Severity.COMMON)
m.editMessage(event.getClient().getError()+" Error loading: "+throwable.getMessage()).queue();
else
m.editMessage(event.getClient().getError()+" Error loading track.").queue();
}
}
}
@@ -1,70 +1,69 @@
/*
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import me.jagrosh.jdautilities.commandclient.Command;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.utils.OtherUtil;
import net.dv8tion.jda.core.entities.Icon;
import net.dv8tion.jda.core.exceptions.RateLimitedException;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SetavatarCmd extends Command {
public SetavatarCmd(Bot bot)
{
this.name = "setavatar";
this.help = "sets the name of the bot";
this.arguments = "<url>";
this.ownerCommand = true;
this.category = bot.OWNER;
}
@Override
protected void execute(CommandEvent event) {
String url;
if(event.getArgs().isEmpty())
if(!event.getMessage().getAttachments().isEmpty() && event.getMessage().getAttachments().get(0).isImage())
url = event.getMessage().getAttachments().get(0).getUrl();
else
url = null;
else
url = event.getArgs();
InputStream s = OtherUtil.imageFromUrl(url);
if(s==null)
{
event.reply(event.getClient().getError()+" Invalid or missing URL");
}
else
{
try {
event.getSelfUser().getManager().setAvatar(Icon.from(s)).queue(
v -> event.reply(event.getClient().getSuccess()+" Successfully changed avatar."),
t -> event.reply(event.getClient().getError()+" Failed to set avatar."));
} catch(IOException e) {
event.reply(event.getClient().getError()+" Could not load from provided URL.");
}
}
}
}
/*
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.utils.OtherUtil;
import net.dv8tion.jda.core.entities.Icon;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SetavatarCmd extends Command {
public SetavatarCmd(Bot bot)
{
this.name = "setavatar";
this.help = "sets the avatar of the bot";
this.arguments = "<url>";
this.ownerCommand = true;
this.category = bot.OWNER;
}
@Override
protected void execute(CommandEvent event) {
String url;
if(event.getArgs().isEmpty())
if(!event.getMessage().getAttachments().isEmpty() && event.getMessage().getAttachments().get(0).isImage())
url = event.getMessage().getAttachments().get(0).getUrl();
else
url = null;
else
url = event.getArgs();
InputStream s = OtherUtil.imageFromUrl(url);
if(s==null)
{
event.reply(event.getClient().getError()+" Invalid or missing URL");
}
else
{
try {
event.getSelfUser().getManager().setAvatar(Icon.from(s)).queue(
v -> event.reply(event.getClient().getSuccess()+" Successfully changed avatar."),
t -> event.reply(event.getClient().getError()+" Failed to set avatar."));
} catch(IOException e) {
event.reply(event.getClient().getError()+" Could not load from provided URL.");
}
}
}
}
@@ -1,69 +1,69 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import java.util.List;
import me.jagrosh.jdautilities.commandclient.Command;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.utils.FinderUtil;
import me.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.entities.Role;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SetdjCmd extends Command {
private final Bot bot;
public SetdjCmd(Bot bot)
{
this.bot = bot;
this.name = "setdj";
this.help = "sets the DJ role for certain music commands";
this.arguments = "<rolename|NONE>";
this.guildOnly = true;
this.category = bot.ADMIN;
}
@Override
protected void execute(CommandEvent event) {
if(event.getArgs().isEmpty())
{
event.reply(event.getClient().getError()+" Please include a role name or NONE");
}
else if(event.getArgs().equalsIgnoreCase("none"))
{
bot.clearTextChannel(event.getGuild());
event.reply(event.getClient().getSuccess()+" DJ role cleared; Only Admins can use the DJ commands.");
}
else
{
List<Role> list = FinderUtil.findRole(event.getArgs(), event.getGuild());
if(list.isEmpty())
event.reply(event.getClient().getWarning()+" No Roles found matching \""+event.getArgs()+"\"");
else if (list.size()>1)
event.reply(event.getClient().getWarning()+FormatUtil.listOfRoles(list, event.getArgs()));
else
{
bot.setRole(list.get(0));
event.reply(event.getClient().getSuccess()+" DJ commands can now be used by users with the **"+list.get(0).getName()+"** role.");
}
}
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import java.util.List;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.utils.FinderUtil;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.entities.Role;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SetdjCmd extends Command {
private final Bot bot;
public SetdjCmd(Bot bot)
{
this.bot = bot;
this.name = "setdj";
this.help = "sets the DJ role for certain music commands";
this.arguments = "<rolename|NONE>";
this.guildOnly = true;
this.category = bot.ADMIN;
}
@Override
protected void execute(CommandEvent event) {
if(event.getArgs().isEmpty())
{
event.reply(event.getClient().getError()+" Please include a role name or NONE");
}
else if(event.getArgs().equalsIgnoreCase("none"))
{
bot.clearRole(event.getGuild());
event.reply(event.getClient().getSuccess()+" DJ role cleared; Only Admins can use the DJ commands.");
}
else
{
List<Role> list = FinderUtil.findRole(event.getArgs(), event.getGuild());
if(list.isEmpty())
event.reply(event.getClient().getWarning()+" No Roles found matching \""+event.getArgs()+"\"");
else if (list.size()>1)
event.reply(event.getClient().getWarning()+FormatUtil.listOfRoles(list, event.getArgs()));
else
{
bot.setRole(list.get(0));
event.reply(event.getClient().getSuccess()+" DJ commands can now be used by users with the **"+list.get(0).getName()+"** role.");
}
}
}
}
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
package com.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.Command;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import net.dv8tion.jda.core.entities.Game;
/**
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
package com.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.Command;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import net.dv8tion.jda.core.exceptions.RateLimitedException;
/**
@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
package com.jagrosh.jmusicbot.commands;
import java.util.List;
import me.jagrosh.jdautilities.commandclient.Command;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.utils.FinderUtil;
import me.jagrosh.jmusicbot.utils.FormatUtil;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.utils.FinderUtil;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.entities.TextChannel;
/**
@@ -1,65 +1,67 @@
/*
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.Command;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.Settings;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.MessageBuilder;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.VoiceChannel;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SettingsCmd extends Command {
private final Bot bot;
public SettingsCmd(Bot bot)
{
this.bot = bot;
this.name = "settings";
this.help = "shows the bots settings";
this.aliases = new String[]{"status"};
this.guildOnly = true;
}
@Override
protected void execute(CommandEvent event) {
Settings s = bot.getSettings(event.getGuild());
MessageBuilder builder = new MessageBuilder()
.append("\uD83C\uDFA7 **")
.append(event.getSelfUser().getName())
.append("** settings:");
TextChannel tchan = event.getGuild().getTextChannelById(s.getTextId());
VoiceChannel vchan = event.getGuild().getVoiceChannelById(s.getVoiceId());
Role role = event.getGuild().getRoleById(s.getRoleId());
EmbedBuilder ebuilder = new EmbedBuilder()
.setColor(event.getSelfMember().getColor())
.setDescription("Text Channel: "+(tchan==null ? "Any" : "**#"+tchan.getName()+"**")
+ "\nVoice Channel: "+(vchan==null ? "Any" : "**"+vchan.getName()+"**")
+ "\nDJ Role: "+(role==null ? "None" : "**"+role.getName()+"**"))
.setFooter(event.getJDA().getGuilds().size()+" servers | "
+event.getJDA().getGuilds().stream().filter(g -> g.getSelfMember().getVoiceState().inVoiceChannel()).count()
+" audio connections", null);
event.getChannel().sendMessage(builder.setEmbed(ebuilder.build()).build()).queue();
}
}
/*
* Copyright 2017 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.Settings;
import net.dv8tion.jda.core.EmbedBuilder;
import net.dv8tion.jda.core.MessageBuilder;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.VoiceChannel;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SettingsCmd extends Command {
private final Bot bot;
public SettingsCmd(Bot bot)
{
this.bot = bot;
this.name = "settings";
this.help = "shows the bots settings";
this.aliases = new String[]{"status"};
this.guildOnly = true;
}
@Override
protected void execute(CommandEvent event) {
Settings s = bot.getSettings(event.getGuild());
MessageBuilder builder = new MessageBuilder()
.append("\uD83C\uDFA7 **")
.append(event.getSelfUser().getName())
.append("** settings:");
TextChannel tchan = event.getGuild().getTextChannelById(s.getTextId());
VoiceChannel vchan = event.getGuild().getVoiceChannelById(s.getVoiceId());
Role role = event.getGuild().getRoleById(s.getRoleId());
EmbedBuilder ebuilder = new EmbedBuilder()
.setColor(event.getSelfMember().getColor())
.setDescription("Text Channel: "+(tchan==null ? "Any" : "**#"+tchan.getName()+"**")
+ "\nVoice Channel: "+(vchan==null ? "Any" : "**"+vchan.getName()+"**")
+ "\nDJ Role: "+(role==null ? "None" : "**"+role.getName()+"**")
+ "\nDefault Playlist: "+(s.getDefaultPlaylist()==null ? "None" : "**"+s.getDefaultPlaylist()+"**")
)
.setFooter(event.getJDA().getGuilds().size()+" servers | "
+event.getJDA().getGuilds().stream().filter(g -> g.getSelfMember().getVoiceState().inVoiceChannel()).count()
+" audio connections", null);
event.getChannel().sendMessage(builder.setEmbed(ebuilder.build()).build()).queue();
}
}
@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
package com.jagrosh.jmusicbot.commands;
import java.util.List;
import me.jagrosh.jdautilities.commandclient.Command;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.utils.FinderUtil;
import me.jagrosh.jmusicbot.utils.FormatUtil;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.utils.FinderUtil;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.entities.VoiceChannel;
/**
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
package com.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
/**
*
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
package com.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.Command;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import com.jagrosh.jdautilities.commandclient.Command;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
/**
*
@@ -1,75 +1,80 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.audio.AudioHandler;
import net.dv8tion.jda.core.entities.User;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SkipCmd extends MusicCommand {
public SkipCmd(Bot bot)
{
super(bot);
this.name = "skip";
this.help = "votes to skip the current song";
this.aliases = new String[]{"voteskip"};
this.beListening = true;
this.bePlaying = true;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
if(event.getAuthor().getId().equals(handler.getCurrentTrack().getIdentifier()))
{
event.reply(event.getClient().getSuccess()+" Skipped **"+handler.getCurrentTrack().getTrack().getInfo().title
+"**");
handler.getPlayer().stopTrack();
}
else
{
int listeners = (int)event.getSelfMember().getVoiceState().getChannel().getMembers().stream()
.filter(m -> !m.getUser().isBot() && !m.getVoiceState().isDeafened()).count();
String msg;
if(handler.getVotes().contains(event.getAuthor().getId()))
msg = event.getClient().getWarning()+" You already voted to skip this song `[";
else
{
msg = event.getClient().getSuccess()+" You voted to skip the song `[";
handler.getVotes().add(event.getAuthor().getId());
}
int skippers = (int)event.getSelfMember().getVoiceState().getChannel().getMembers().stream()
.filter(m -> handler.getVotes().contains(m.getUser().getId())).count();
int required = (int)Math.ceil(listeners * .55);
msg+= skippers+" votes, "+required+"/"+listeners+" needed]`";
if(skippers>=required)
{
User u = event.getJDA().getUserById(handler.getCurrentTrack().getIdentifier());
msg+="\n"+event.getClient().getSuccess()+" Skipped **"+handler.getCurrentTrack().getTrack().getInfo().title
+"** (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")";
handler.getPlayer().stopTrack();
}
event.reply(msg);
}
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import net.dv8tion.jda.core.entities.User;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SkipCmd extends MusicCommand {
public SkipCmd(Bot bot)
{
super(bot);
this.name = "skip";
this.help = "votes to skip the current song";
this.aliases = new String[]{"voteskip"};
this.beListening = true;
this.bePlaying = true;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
if(event.getAuthor().getId().equals(handler.getCurrentTrack().getIdentifier()))
{
event.reply(event.getClient().getSuccess()+" Skipped **"+handler.getCurrentTrack().getTrack().getInfo().title
+"**");
handler.getPlayer().stopTrack();
}
else
{
int listeners = (int)event.getSelfMember().getVoiceState().getChannel().getMembers().stream()
.filter(m -> !m.getUser().isBot() && !m.getVoiceState().isDeafened()).count();
String msg;
if(handler.getVotes().contains(event.getAuthor().getId()))
msg = event.getClient().getWarning()+" You already voted to skip this song `[";
else
{
msg = event.getClient().getSuccess()+" You voted to skip the song `[";
handler.getVotes().add(event.getAuthor().getId());
}
int skippers = (int)event.getSelfMember().getVoiceState().getChannel().getMembers().stream()
.filter(m -> handler.getVotes().contains(m.getUser().getId())).count();
int required = (int)Math.ceil(listeners * .55);
msg+= skippers+" votes, "+required+"/"+listeners+" needed]`";
if(skippers>=required)
{
User u;
try {
u = event.getJDA().getUserById(handler.getCurrentTrack().getIdentifier());
} catch(Exception e) {
u = null;
}
msg+="\n"+event.getClient().getSuccess()+" Skipped **"+handler.getCurrentTrack().getTrack().getInfo().title
+"**"+(handler.getCurrentTrack().getIdentifier()==null ? "" : " (requested by "+(u==null ? "someone" : "**"+u.getName()+"**")+")");
handler.getPlayer().stopTrack();
}
event.reply(msg);
}
}
}
@@ -1,63 +1,63 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.audio.AudioHandler;
import net.dv8tion.jda.core.entities.User;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SkiptoCmd extends MusicCommand {
public SkiptoCmd(Bot bot)
{
super(bot);
this.name = "skipto";
this.help = "skips to the current song";
this.arguments = "<position>";
this.aliases = new String[]{"jumpto"};
this.bePlaying = true;
this.category = bot.DJ;
}
@Override
public void doCommand(CommandEvent event) {
int index = 0;
try
{
index = Integer.parseInt(event.getArgs());
}
catch(NumberFormatException e)
{
event.reply(event.getClient().getError()+" `"+event.getArgs()+"` is not a valid integer!");
return;
}
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
if(index<1 || index>handler.getQueue().size())
{
event.reply(event.getClient().getError()+" Position must be a valid integer between 1 and "+handler.getQueue().size()+"!");
return;
}
handler.getQueue().skip(index-1);
event.reply(event.getClient().getSuccess()+" Skipped to **"+handler.getQueue().get(0).getTrack().getInfo().title+"**");
handler.getPlayer().stopTrack();
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import net.dv8tion.jda.core.entities.User;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class SkiptoCmd extends MusicCommand {
public SkiptoCmd(Bot bot)
{
super(bot);
this.name = "skipto";
this.help = "skips to the specified song";
this.arguments = "<position>";
this.aliases = new String[]{"jumpto"};
this.bePlaying = true;
this.category = bot.DJ;
}
@Override
public void doCommand(CommandEvent event) {
int index = 0;
try
{
index = Integer.parseInt(event.getArgs());
}
catch(NumberFormatException e)
{
event.reply(event.getClient().getError()+" `"+event.getArgs()+"` is not a valid integer!");
return;
}
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
if(index<1 || index>handler.getQueue().size())
{
event.reply(event.getClient().getError()+" Position must be a valid integer between 1 and "+handler.getQueue().size()+"!");
return;
}
handler.getQueue().skip(index-1);
event.reply(event.getClient().getSuccess()+" Skipped to **"+handler.getQueue().get(0).getTrack().getInfo().title+"**");
handler.getPlayer().stopTrack();
}
}
@@ -1,46 +1,45 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.audio.AudioHandler;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class StopCmd extends MusicCommand {
public StopCmd(Bot bot)
{
super(bot);
this.name = "stop";
this.help = "stops the current song and clears the queue";
this.bePlaying = true;
this.category = bot.DJ;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
handler.getQueue().clear();
handler.getPlayer().stopTrack();
event.getGuild().getAudioManager().closeAudioConnection();
event.reply(event.getClient().getSuccess()+" The player has stopped and the queue has been cleared.");
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class StopCmd extends MusicCommand {
public StopCmd(Bot bot)
{
super(bot);
this.name = "stop";
this.help = "stops the current song and clears the queue";
this.bePlaying = true;
this.category = bot.DJ;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
handler.stopAndClear();
event.getGuild().getAudioManager().closeAudioConnection();
event.reply(event.getClient().getSuccess()+" The player has stopped and the queue has been cleared.");
}
}
@@ -1,64 +1,66 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.audio.AudioHandler;
import me.jagrosh.jmusicbot.utils.FormatUtil;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class VolumeCmd extends MusicCommand {
public VolumeCmd(Bot bot)
{
super(bot);
this.name = "volume";
this.help = "sets or shows volume";
this.arguments = "[0-150]";
this.category = bot.DJ;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
int volume = handler==null ? 100 : handler.getPlayer().getVolume();
if(event.getArgs().isEmpty())
{
event.reply(FormatUtil.volumeIcon(volume)+" Current volume is `"+volume+"`");
}
else
{
int nvolume;
try{
nvolume = Integer.parseInt(event.getArgs());
}catch(NumberFormatException e){
nvolume = -1;
}
if(nvolume<0 || nvolume>150)
event.reply(event.getClient().getError()+" Volume must be a valid integer between 0 and 150!");
else
{
bot.setUpHandler(event).getPlayer().setVolume(nvolume);
event.reply(FormatUtil.volumeIcon(nvolume)+" Volume changed from `"+volume+"` to `"+nvolume+"`");
}
}
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.commands;
import com.jagrosh.jdautilities.commandclient.CommandEvent;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.utils.FormatUtil;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class VolumeCmd extends MusicCommand {
public VolumeCmd(Bot bot)
{
super(bot);
this.name = "volume";
this.aliases = new String[]{"vol"};
this.help = "sets or shows volume";
this.arguments = "[0-150]";
this.category = bot.DJ;
}
@Override
public void doCommand(CommandEvent event) {
AudioHandler handler = (AudioHandler)event.getGuild().getAudioManager().getSendingHandler();
int volume = handler==null && bot.getSettings(event.getGuild())==null ? 100 : (handler==null ? bot.getSettings(event.getGuild()).getVolume() : handler.getPlayer().getVolume());
if(event.getArgs().isEmpty())
{
event.reply(FormatUtil.volumeIcon(volume)+" Current volume is `"+volume+"`");
}
else
{
int nvolume;
try{
nvolume = Integer.parseInt(event.getArgs());
}catch(NumberFormatException e){
nvolume = -1;
}
if(nvolume<0 || nvolume>150)
event.reply(event.getClient().getError()+" Volume must be a valid integer between 0 and 150!");
else
{
bot.setUpHandler(event).getPlayer().setVolume(nvolume);
bot.setVolume(event.getGuild(), nvolume);
event.reply(FormatUtil.volumeIcon(nvolume)+" Volume changed from `"+volume+"` to `"+nvolume+"`");
}
}
}
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.gui;
package com.jagrosh.jmusicbot.gui;
import java.awt.Dimension;
import java.awt.GridLayout;
@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.gui;
package com.jagrosh.jmusicbot.gui;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
import javax.swing.WindowConstants;
import me.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.Bot;
/**
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.gui;
package com.jagrosh.jmusicbot.gui;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
@@ -26,9 +26,9 @@ import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.audio.AudioHandler;
import me.jagrosh.jmusicbot.utils.FormatUtil;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import com.jagrosh.jmusicbot.utils.FormatUtil;
import net.dv8tion.jda.core.entities.Guild;
/**
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.gui;
package com.jagrosh.jmusicbot.gui;
import java.awt.*;
import java.io.*;
@@ -0,0 +1,257 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.jagrosh.jmusicbot.playlist;
import com.jagrosh.jmusicbot.Bot;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
*
* @author John Grosh (john.a.grosh@gmail.com)
*/
public class Playlist {
private final String name;
private final List<String> items;
private List<AudioTrack> tracks;
private List<PlaylistLoadError> errors;
private final boolean shuffle;
private Playlist(String name, List<String> items, boolean shuffle)
{
this.name = name;
this.items = items;
this.shuffle = shuffle;
}
public void loadTracks(AudioPlayerManager manager, Consumer<AudioTrack> consumer, Runnable callback)
{
if(tracks==null)
{
tracks = new LinkedList<>();
errors = new LinkedList<>();
for(int i=0; i<items.size(); i++)
{
boolean last = i+1==items.size();
int index = i;
manager.loadItemOrdered(name, items.get(i), new AudioLoadResultHandler() {
@Override
public void trackLoaded(AudioTrack at) {
tracks.add(at);
consumer.accept(at);
if(last)
{
if(callback!=null)
callback.run();
}
}
@Override
public void playlistLoaded(AudioPlaylist ap) {
if(ap.isSearchResult())
{
tracks.add(ap.getTracks().get(0));
consumer.accept(ap.getTracks().get(0));
}
else if(ap.getSelectedTrack()!=null)
{
tracks.add(ap.getSelectedTrack());
consumer.accept(ap.getSelectedTrack());
}
else
{
List<AudioTrack> loaded = new ArrayList<>(ap.getTracks());
if(shuffle)
for(int first =0; first<loaded.size(); first++)
{
int second = (int)(Math.random()*loaded.size());
AudioTrack tmp = loaded.get(first);
loaded.set(first, loaded.get(second));
loaded.set(second, tmp);
}
tracks.addAll(loaded);
loaded.forEach(at -> consumer.accept(at));
}
if(last)
{
if(callback!=null)
callback.run();
}
}
@Override
public void noMatches() {
errors.add(new PlaylistLoadError(index, items.get(index), "No matches found."));
if(last)
{
if(callback!=null)
callback.run();
}
}
@Override
public void loadFailed(FriendlyException fe) {
errors.add(new PlaylistLoadError(index, items.get(index), "Failed to load track: "+fe.getLocalizedMessage()));
if(last)
{
if(callback!=null)
callback.run();
}
}
});
}
}
}
public String getName()
{
return name;
}
public List<String> getItems()
{
return items;
}
public List<AudioTrack> getTracks()
{
return tracks;
}
public void shuffleTracks()
{
if(tracks!=null)
{
for(int first =0; first<tracks.size(); first++)
{
int second = (int)(Math.random()*tracks.size());
AudioTrack tmp = tracks.get(first);
tracks.set(first, tracks.get(second));
tracks.set(second, tmp);
}
}
}
public List<PlaylistLoadError> getErrors()
{
return errors;
}
public static void createFolder()
{
try
{
Files.createDirectory(Paths.get("Playlists"));
} catch (IOException ex)
{}
}
public static boolean folderExists()
{
return Files.exists(Paths.get("Playlists"));
}
public static List<String> getPlaylists()
{
if(folderExists())
{
File folder = new File("Playlists");
return Arrays.asList(folder.listFiles((pathname) -> pathname.getName().endsWith(".txt")))
.stream().map(f -> f.getName().substring(0,f.getName().length()-4)).collect(Collectors.toList());
}
else
{
createFolder();
return null;
}
}
public static Playlist loadPlaylist(String name)
{
try
{
if(folderExists())
{
boolean[] shuffle = {false};
List<String> list = new ArrayList<>();
Files.readAllLines(Paths.get("Playlists"+File.separator+name+".txt")).forEach(str -> {
String s = str.trim();
if(s.isEmpty())
return;
if(s.startsWith("#") || s.startsWith("//"))
{
s = s.replaceAll("\\s+", "");
if(s.equalsIgnoreCase("#shuffle") || s.equalsIgnoreCase("//shuffle"))
shuffle[0]=true;
}
else
list.add(s);
});
if(shuffle[0])
{
for(int first =0; first<list.size(); first++)
{
int second = (int)(Math.random()*list.size());
String tmp = list.get(first);
list.set(first, list.get(second));
list.set(second, tmp);
}
}
return new Playlist(name, list, shuffle[0]);
}
else
{
createFolder();
return null;
}
}
catch(IOException e)
{
return null;
}
}
public class PlaylistLoadError {
private final int number;
private final String item;
private final String reason;
private PlaylistLoadError(int number, String item, String reason)
{
this.number = number;
this.item = item;
this.reason = reason;
}
public int getIndex()
{
return number;
}
public String getItem()
{
return item;
}
public String getReason()
{
return reason;
}
}
}
@@ -1,108 +1,123 @@
/*
* Copyright 2016 John Grosh (jagrosh).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.queue;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
*
* @author John Grosh (jagrosh)
*/
public class FairQueue<T extends Queueable> {
private final List<T> list = new ArrayList<>();
private final Set<String> set = new HashSet<>();
public int add(T item)
{
int lastIndex;
for(lastIndex=list.size()-1; lastIndex>-1; lastIndex--)
if(list.get(lastIndex).getIdentifier().equals(item.getIdentifier()))
break;
lastIndex++;
set.clear();
for(; lastIndex<list.size(); lastIndex++)
{
if(set.contains(list.get(lastIndex).getIdentifier()))
break;
set.add(list.get(lastIndex).getIdentifier());
}
list.add(lastIndex, item);
return lastIndex;
}
public int size()
{
return list.size();
}
public T pull()
{
return list.remove(0);
}
public boolean isEmpty()
{
return list.isEmpty();
}
public List<T> getList()
{
return list;
}
public T get(int index)
{
return list.get(index);
}
public T remove(int index)
{
return list.remove(index);
}
public void clear()
{
list.clear();
}
public int shuffle(String identifier)
{
List<Integer> iset = new ArrayList<>();
for(int i=0; i<list.size(); i++)
{
if(list.get(i).getIdentifier().equals(identifier))
iset.add(i);
}
for(int j=0; j<iset.size(); j++)
{
int first = iset.get(j);
int second = iset.get((int)(Math.random()*iset.size()));
T temp = list.get(first);
list.set(first, list.get(second));
list.set(second, temp);
}
return iset.size();
}
public void skip(int number)
{
for(int i=0; i<number; i++)
list.remove(0);
}
}
/*
* Copyright 2016 John Grosh (jagrosh).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.queue;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
*
* @author John Grosh (jagrosh)
* @param <T>
*/
public class FairQueue<T extends Queueable> {
private final List<T> list = new ArrayList<>();
private final Set<String> set = new HashSet<>();
public int add(T item)
{
int lastIndex;
for(lastIndex=list.size()-1; lastIndex>-1; lastIndex--)
if(list.get(lastIndex).getIdentifier().equals(item.getIdentifier()))
break;
lastIndex++;
set.clear();
for(; lastIndex<list.size(); lastIndex++)
{
if(set.contains(list.get(lastIndex).getIdentifier()))
break;
set.add(list.get(lastIndex).getIdentifier());
}
list.add(lastIndex, item);
return lastIndex;
}
public int size()
{
return list.size();
}
public T pull()
{
return list.remove(0);
}
public boolean isEmpty()
{
return list.isEmpty();
}
public List<T> getList()
{
return list;
}
public T get(int index)
{
return list.get(index);
}
public T remove(int index)
{
return list.remove(index);
}
public int removeAll(String identifier)
{
int count = 0;
for(int i=list.size()-1; i>=0; i--)
{
if(list.get(i).getIdentifier().equals(identifier))
{
list.remove(i);
count++;
}
}
return count;
}
public void clear()
{
list.clear();
}
public int shuffle(String identifier)
{
List<Integer> iset = new ArrayList<>();
for(int i=0; i<list.size(); i++)
{
if(list.get(i).getIdentifier().equals(identifier))
iset.add(i);
}
for(int j=0; j<iset.size(); j++)
{
int first = iset.get(j);
int second = iset.get((int)(Math.random()*iset.size()));
T temp = list.get(first);
list.set(first, list.get(second));
list.set(second, temp);
}
return iset.size();
}
public void skip(int number)
{
for(int i=0; i<number; i++)
list.remove(0);
}
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.queue;
package com.jagrosh.jmusicbot.queue;
/**
*
@@ -1,140 +1,156 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.VoiceChannel;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class FinderUtil {
public static List<TextChannel> findTextChannel(String query, Guild guild)
{
String id;
if(query.matches("<#\\d+>"))
{
id = query.replaceAll("<#(\\d+)>", "$1");
TextChannel tc = guild.getJDA().getTextChannelById(id);
if(tc!=null && tc.getGuild().equals(guild))
return Collections.singletonList(tc);
}
ArrayList<TextChannel> exact = new ArrayList<>();
ArrayList<TextChannel> wrongcase = new ArrayList<>();
ArrayList<TextChannel> startswith = new ArrayList<>();
ArrayList<TextChannel> contains = new ArrayList<>();
String lowerquery = query.toLowerCase();
guild.getTextChannels().stream().forEach((tc) -> {
if(tc.getName().equals(lowerquery))
exact.add(tc);
else if (tc.getName().equalsIgnoreCase(lowerquery) && exact.isEmpty())
wrongcase.add(tc);
else if (tc.getName().toLowerCase().startsWith(lowerquery) && wrongcase.isEmpty())
startswith.add(tc);
else if (tc.getName().toLowerCase().contains(lowerquery) && startswith.isEmpty())
contains.add(tc);
});
if(!exact.isEmpty())
return exact;
if(!wrongcase.isEmpty())
return wrongcase;
if(!startswith.isEmpty())
return startswith;
return contains;
}
public static List<VoiceChannel> findVoiceChannel(String query, Guild guild)
{
String id;
if(query.matches("<#\\d+>"))
{
id = query.replaceAll("<#(\\d+)>", "$1");
VoiceChannel tc = guild.getJDA().getVoiceChannelById(id);
if(tc!=null && tc.getGuild().equals(guild))
return Collections.singletonList(tc);
}
ArrayList<VoiceChannel> exact = new ArrayList<>();
ArrayList<VoiceChannel> wrongcase = new ArrayList<>();
ArrayList<VoiceChannel> startswith = new ArrayList<>();
ArrayList<VoiceChannel> contains = new ArrayList<>();
String lowerquery = query.toLowerCase();
guild.getVoiceChannels().stream().forEach((tc) -> {
if(tc.getName().equals(lowerquery))
exact.add(tc);
else if (tc.getName().equalsIgnoreCase(lowerquery) && exact.isEmpty())
wrongcase.add(tc);
else if (tc.getName().toLowerCase().startsWith(lowerquery) && wrongcase.isEmpty())
startswith.add(tc);
else if (tc.getName().toLowerCase().contains(lowerquery) && startswith.isEmpty())
contains.add(tc);
});
if(!exact.isEmpty())
return exact;
if(!wrongcase.isEmpty())
return wrongcase;
if(!startswith.isEmpty())
return startswith;
return contains;
}
public static List<Role> findRole(String query, Guild guild)
{
String id;
if(query.matches("<@&\\d+>"))
{
id = query.replaceAll("<@&(\\d+)>", "$1");
Role role = guild.getRoleById(id);
if(role!=null)
return Collections.singletonList(role);
}
if(query.matches("[Ii][Dd]\\s*:\\s*\\d+"))
{
id = query.replaceAll("[Ii][Dd]\\s*:\\s*(\\d+)", "$1");
for(Role role: guild.getRoles())
if(role.getId().equals(id))
return Collections.singletonList(role);
}
ArrayList<Role> exact = new ArrayList<>();
ArrayList<Role> wrongcase = new ArrayList<>();
ArrayList<Role> startswith = new ArrayList<>();
ArrayList<Role> contains = new ArrayList<>();
String lowerQuery = query.toLowerCase();
guild.getRoles().stream().forEach((role) -> {
if(role.getName().equals(query))
exact.add(role);
else if (role.getName().equalsIgnoreCase(query) && exact.isEmpty())
wrongcase.add(role);
else if (role.getName().toLowerCase().startsWith(lowerQuery) && wrongcase.isEmpty())
startswith.add(role);
else if (role.getName().toLowerCase().contains(lowerQuery) && startswith.isEmpty())
contains.add(role);
});
if(!exact.isEmpty())
return exact;
if(!wrongcase.isEmpty())
return wrongcase;
if(!startswith.isEmpty())
return startswith;
return contains;
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.VoiceChannel;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class FinderUtil {
public final static String DISCORD_ID = "\\d{17,20}";
public static List<TextChannel> findTextChannel(String query, Guild guild)
{
String id;
if(query.matches("<#\\d+>"))
{
id = query.replaceAll("<#(\\d+)>", "$1");
TextChannel tc = guild.getJDA().getTextChannelById(id);
if(tc!=null && tc.getGuild().equals(guild))
return Collections.singletonList(tc);
}
else if(query.matches(DISCORD_ID))
{
id = query;
TextChannel tc = guild.getJDA().getTextChannelById(id);
if(tc!=null && tc.getGuild().equals(guild))
return Collections.singletonList(tc);
}
ArrayList<TextChannel> exact = new ArrayList<>();
ArrayList<TextChannel> wrongcase = new ArrayList<>();
ArrayList<TextChannel> startswith = new ArrayList<>();
ArrayList<TextChannel> contains = new ArrayList<>();
String lowerquery = query.toLowerCase();
guild.getTextChannels().stream().forEach((tc) -> {
if(tc.getName().equals(lowerquery))
exact.add(tc);
else if (tc.getName().equalsIgnoreCase(lowerquery) && exact.isEmpty())
wrongcase.add(tc);
else if (tc.getName().toLowerCase().startsWith(lowerquery) && wrongcase.isEmpty())
startswith.add(tc);
else if (tc.getName().toLowerCase().contains(lowerquery) && startswith.isEmpty())
contains.add(tc);
});
if(!exact.isEmpty())
return exact;
if(!wrongcase.isEmpty())
return wrongcase;
if(!startswith.isEmpty())
return startswith;
return contains;
}
public static List<VoiceChannel> findVoiceChannel(String query, Guild guild)
{
String id;
if(query.matches("<#\\d+>"))
{
id = query.replaceAll("<#(\\d+)>", "$1");
VoiceChannel vc = guild.getJDA().getVoiceChannelById(id);
if(vc!=null && vc.getGuild().equals(guild))
return Collections.singletonList(vc);
}
else if(query.matches(DISCORD_ID))
{
id = query;
VoiceChannel vc = guild.getJDA().getVoiceChannelById(id);
if(vc!=null && vc.getGuild().equals(guild))
return Collections.singletonList(vc);
}
ArrayList<VoiceChannel> exact = new ArrayList<>();
ArrayList<VoiceChannel> wrongcase = new ArrayList<>();
ArrayList<VoiceChannel> startswith = new ArrayList<>();
ArrayList<VoiceChannel> contains = new ArrayList<>();
String lowerquery = query.toLowerCase();
guild.getVoiceChannels().stream().forEach((vc) -> {
if(vc.getName().equals(lowerquery))
exact.add(vc);
else if (vc.getName().equalsIgnoreCase(lowerquery) && exact.isEmpty())
wrongcase.add(vc);
else if (vc.getName().toLowerCase().startsWith(lowerquery) && wrongcase.isEmpty())
startswith.add(vc);
else if (vc.getName().toLowerCase().contains(lowerquery) && startswith.isEmpty())
contains.add(vc);
});
if(!exact.isEmpty())
return exact;
if(!wrongcase.isEmpty())
return wrongcase;
if(!startswith.isEmpty())
return startswith;
return contains;
}
public static List<Role> findRole(String query, Guild guild)
{
String id;
if(query.matches("<@&\\d+>"))
{
id = query.replaceAll("<@&(\\d+)>", "$1");
Role r = guild.getRoleById(id);
if(r!=null)
return Collections.singletonList(r);
}
else if(query.matches(DISCORD_ID))
{
id = query;
Role r = guild.getRoleById(id);
if(r!=null)
return Collections.singletonList(r);
}
ArrayList<Role> exact = new ArrayList<>();
ArrayList<Role> wrongcase = new ArrayList<>();
ArrayList<Role> startswith = new ArrayList<>();
ArrayList<Role> contains = new ArrayList<>();
String lowerQuery = query.toLowerCase();
guild.getRoles().stream().forEach((role) -> {
if(role.getName().equals(query))
exact.add(role);
else if (role.getName().equalsIgnoreCase(query) && exact.isEmpty())
wrongcase.add(role);
else if (role.getName().toLowerCase().startsWith(lowerQuery) && wrongcase.isEmpty())
startswith.add(role);
else if (role.getName().toLowerCase().contains(lowerQuery) && startswith.isEmpty())
contains.add(role);
});
if(!exact.isEmpty())
return exact;
if(!wrongcase.isEmpty())
return wrongcase;
if(!startswith.isEmpty())
return startswith;
return contains;
}
}
@@ -1,116 +1,126 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.utils;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import java.util.List;
import me.jagrosh.jmusicbot.audio.AudioHandler;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.User;
import net.dv8tion.jda.core.entities.VoiceChannel;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class FormatUtil {
public static String formatTime(long duration)
{
if(duration == Long.MAX_VALUE)
return "LIVE";
long seconds = Math.round(duration/1000.0);
long hours = seconds/(60*60);
seconds %= 60*60;
long minutes = seconds/60;
seconds %= 60;
return (hours>0 ? hours+":" : "") + (minutes<10 ? "0"+minutes : minutes) + ":" + (seconds<10 ? "0"+seconds : seconds);
}
public static String formattedAudio(AudioHandler handler, JDA jda, boolean inTopic)
{
if(handler==null)
return "No music playing\n\u23F9 "+progressBar(-1)+" "+volumeIcon(100);
else if (handler.getCurrentTrack()==null)
return "No music playing\n\u23F9 "+progressBar(-1)+" "+volumeIcon(handler.getPlayer().getVolume());
else
{
String userid = handler.getCurrentTrack().getIdentifier();
User user = jda.getUserById(userid);
AudioTrack track = handler.getCurrentTrack().getTrack();
String title = track.getInfo().title;
if(inTopic && title.length()>30)
title = title.substring(0,27)+"...";
double progress = (double)track.getPosition()/track.getDuration();
String str = "**"+title+"** ["+(user==null||inTopic ? "<@"+userid+">" : user.getName())+"]\n\u25B6 "+progressBar(progress)
+" "+(inTopic ? "" : "`")+"["+formatTime(track.getPosition()) + "/" + formatTime(track.getDuration())
+"]"+(inTopic ? "" : "`")+" " +volumeIcon(handler.getPlayer().getVolume());
return str;
}
}
private static String progressBar(double percent)
{
String str = "";
for(int i=0; i<10; i++)
if(i == (int)(percent*10))
str+="\uD83D\uDD18";
else
str+="▬";
return str;
}
public static String volumeIcon(int volume)
{
if(volume == 0)
return "\uD83D\uDD07";
if(volume < 30)
return "\uD83D\uDD08";
if(volume < 70)
return "\uD83D\uDD09";
return "\uD83D\uDD0A";
}
public static String listOfTChannels(List<TextChannel> list, String query)
{
String out = " Multiple text channels found matching \""+query+"\":";
for(int i=0; i<6 && i<list.size(); i++)
out+="\n - "+list.get(i).getName()+" (<#"+list.get(i).getId()+">)";
if(list.size()>6)
out+="\n**And "+(list.size()-6)+" more...**";
return out;
}
public static String listOfVChannels(List<VoiceChannel> list, String query)
{
String out = " Multiple voice channels found matching \""+query+"\":";
for(int i=0; i<6 && i<list.size(); i++)
out+="\n - "+list.get(i).getName()+" (ID:"+list.get(i).getId()+")";
if(list.size()>6)
out+="\n**And "+(list.size()-6)+" more...**";
return out;
}
public static String listOfRoles(List<Role> list, String query)
{
String out = " Multiple text channels found matching \""+query+"\":";
for(int i=0; i<6 && i<list.size(); i++)
out+="\n - "+list.get(i).getName()+" (ID:"+list.get(i).getId()+")";
if(list.size()>6)
out+="\n**And "+(list.size()-6)+" more...**";
return out;
}
}
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jagrosh.jmusicbot.utils;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import java.util.List;
import com.jagrosh.jmusicbot.audio.AudioHandler;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.User;
import net.dv8tion.jda.core.entities.VoiceChannel;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class FormatUtil {
public static boolean NO_PROGRESS_BAR_IN_TOPIC = false;
public static String formatTime(long duration)
{
if(duration == Long.MAX_VALUE)
return "LIVE";
long seconds = Math.round(duration/1000.0);
long hours = seconds/(60*60);
seconds %= 60*60;
long minutes = seconds/60;
seconds %= 60;
return (hours>0 ? hours+":" : "") + (minutes<10 ? "0"+minutes : minutes) + ":" + (seconds<10 ? "0"+seconds : seconds);
}
public static String formattedAudio(AudioHandler handler, JDA jda)
{
if(handler==null)
return "No music playing\n\u23F9 "+progressBar(-1)+" "+volumeIcon(100);
else if (!handler.isMusicPlaying())
return "No music playing\n\u23F9 "+progressBar(-1)+" "+volumeIcon(handler.getPlayer().getVolume());
else
{
String userid = handler.getCurrentTrack().getIdentifier();
AudioTrack track = handler.getCurrentTrack().getTrack();
String title = track.getInfo().title;
if(!NO_PROGRESS_BAR_IN_TOPIC && title.length()>30)
title = title.substring(0,27)+"...";
double progress = (double)track.getPosition()/track.getDuration();
String str = "**"+title+"** ["+(userid==null ? "autoplay" : "<@"+userid+">")+"]";
String str2 = "\n"+(handler.getPlayer().isPaused()?"\u23F8":"\u25B6")+" "
+(NO_PROGRESS_BAR_IN_TOPIC ? "["+formatTime(track.getDuration())+"] " :
progressBar(progress)+" ["+formatTime(track.getPosition()) + "/" + formatTime(track.getDuration())+"] ")
+volumeIcon(handler.getPlayer().getVolume());
return str+str2;
}
}
public static String embedformattedAudio(AudioHandler ah)
{
return (ah.getPlayer().isPaused()?"\u23F8":"\u25B6")+" "+progressBar((double)ah.getCurrentTrack().getTrack().getPosition()/ah.getCurrentTrack().getTrack().getDuration())
+" `["+formatTime(ah.getCurrentTrack().getTrack().getPosition()) + "/" + formatTime(ah.getCurrentTrack().getTrack().getDuration()) +"]` "
+volumeIcon(ah.getPlayer().getVolume());
}
public static String progressBar(double percent)
{
String str = "";
for(int i=0; i<8; i++)
if(i == (int)(percent*8))
str+="\uD83D\uDD18";
else
str+="▬";
return str;
}
public static String volumeIcon(int volume)
{
if(volume == 0)
return "\uD83D\uDD07";
if(volume < 30)
return "\uD83D\uDD08";
if(volume < 70)
return "\uD83D\uDD09";
return "\uD83D\uDD0A";
}
public static String listOfTChannels(List<TextChannel> list, String query)
{
String out = " Multiple text channels found matching \""+query+"\":";
for(int i=0; i<6 && i<list.size(); i++)
out+="\n - "+list.get(i).getName()+" (<#"+list.get(i).getId()+">)";
if(list.size()>6)
out+="\n**And "+(list.size()-6)+" more...**";
return out;
}
public static String listOfVChannels(List<VoiceChannel> list, String query)
{
String out = " Multiple voice channels found matching \""+query+"\":";
for(int i=0; i<6 && i<list.size(); i++)
out+="\n - "+list.get(i).getName()+" (ID:"+list.get(i).getId()+")";
if(list.size()>6)
out+="\n**And "+(list.size()-6)+" more...**";
return out;
}
public static String listOfRoles(List<Role> list, String query)
{
String out = " Multiple text channels found matching \""+query+"\":";
for(int i=0; i<6 && i<list.size(); i++)
out+="\n - "+list.get(i).getName()+" (ID:"+list.get(i).getId()+")";
if(list.size()>6)
out+="\n**And "+(list.size()-6)+" more...**";
return out;
}
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.utils;
package com.jagrosh.jmusicbot.utils;
import java.io.IOException;
import java.io.InputStream;
@@ -1,65 +0,0 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class Settings {
public final static Settings DEFAULT_SETTINGS = new Settings(null, null, null);
private String textId;
private String voiceId;
private String roleId;
public Settings(String textId, String voiceId, String roleId)
{
this.textId = textId;
this.voiceId = voiceId;
this.roleId = roleId;
}
public String getTextId()
{
return textId;
}
public String getVoiceId()
{
return voiceId;
}
public String getRoleId()
{
return roleId;
}
public void setTextId(String id)
{
this.textId = id;
}
public void setVoiceId(String id)
{
this.voiceId = id;
}
public void setRoleId(String id)
{
this.roleId = id;
}
}
@@ -1,42 +0,0 @@
/*
* Copyright 2016 John Grosh <john.a.grosh@gmail.com>.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.jagrosh.jmusicbot.commands;
import me.jagrosh.jdautilities.commandclient.CommandEvent;
import me.jagrosh.jmusicbot.Bot;
import me.jagrosh.jmusicbot.audio.AudioHandler;
import me.jagrosh.jmusicbot.utils.FormatUtil;
/**
*
* @author John Grosh <john.a.grosh@gmail.com>
*/
public class NowplayingCmd extends MusicCommand {
public NowplayingCmd(Bot bot)
{
super(bot);
this.name = "nowplaying";
this.help = "shows the song that is currently playing";
this.aliases = new String[]{"np","current"};
}
@Override
public void doCommand(CommandEvent event) {
event.reply(FormatUtil.formattedAudio((AudioHandler)event.getGuild().getAudioManager().getSendingHandler(), event.getJDA(), false));
}
}