Compare commits

..
24 Commits
Author SHA1 Message Date
Christian F. Brinkmann b419191bad use actual version instead of snapshot in pom.xml 2024-12-06 18:17:37 +01:00
Christian F. Brinkmann aa89145ae8 update readme to reflect that i have now made miniscule dependency changes myself 2024-12-06 18:11:20 +01:00
Christian F. Brinkmann 293733f0e7 bump versions of lavaplayer and lavalink to most recent in the hopes that this fixes something 2024-12-06 17:55:44 +01:00
Christian F. Brinkmann c9a2477f86 Update README.md 2024-10-25 13:26:06 +02:00
root 61a18a1db7 update README to give some info about the fork 2024-10-24 17:24:38 +02:00
root 7fb44e296b Merge branch 'pr-1670', use 1.8.3 instead of 1.8.2 2024-10-24 14:01:24 +02:00
Lythus 4ae9f05776 ignore dockerfile 2024-10-19 21:28:44 +08:00
Lythus 84facb8b82 updated lavalink version to 1.8.3 2024-10-19 20:36:53 +08:00
Michaili K 070938b326 Add anothen message to onTrackError handler 2024-10-15 10:54:27 +02:00
Michaili K 58a9e76edb Formatting changes 2024-10-11 23:42:06 +02:00
Michaili K 96ffcd8291 Handle specific track exceptions with a special message 2024-10-10 20:00:40 +02:00
Michaili K 844a1bb75a Change youtubeoauth2 option description 2024-10-10 19:11:29 +02:00
Michaili K 6094e49ab2 Return early when failing to read the token file 2024-10-10 19:09:05 +02:00
Michaili K 88ce3e1149 Stop logging the refresh token on startup 2024-10-10 19:08:49 +02:00
Michaili K 463bf75783 Prepend "Google" to "accounts" in OAuth2 DM for clarification 2024-10-06 04:56:00 +02:00
Michaili K 348fc3ceec DM the user when the YoutubeOauth2Handler is providing us a token 2024-10-02 21:39:29 +02:00
Lythus 30eafb9239 Updated JDA-Utilities 2024-09-30 15:22:32 +08:00
Michaili K c95f2248f3 Bump youtube-source to 1.8.2 2024-09-26 02:12:38 +02:00
Michail b80b0c8459 Remove accidental HTML tag :) 2024-08-24 14:01:15 +02:00
Michail 4a8392fdb9 Catch potential exceptions thrown by the useOAuth2 call 2024-08-24 13:38:52 +02:00
Michail 9d6584525c Implement YouTube OAuth2 login 2024-08-24 13:25:11 +02:00
Michail 909b655f5c Update YouTube source manager 2024-08-24 12:09:43 +02:00
Michaili K 859e5c5862 Update lavaplayer youtube source to 1.5.2 (#1655) 2024-08-12 13:28:38 -04:00
njezi 43b63f1ba8 fixed a mistake (#1648) 2024-08-06 15:59:19 -04:00
11 changed files with 259 additions and 17 deletions

No files matched your search

+2 -1
View File
@@ -4,4 +4,5 @@
/test/
*.json
*.txt
nb*.xml
nb*.xml
dockerfile
+55
View File
@@ -1,5 +1,60 @@
<img align="right" src="https://i.imgur.com/zrE80HY.png" height="200" width="200">
# This fork
Essentially, this is just a merge of two pull requests:
### Support for logging into your (burner) youtube account:
[PR-1670](https://github.com/jagrosh/MusicBot/pull/1670)
### To allow building the project from source
[PR-1703](https://github.com/jagrosh/MusicBot/pull/1703)
And I've now bumped the versions up to the newest [lavaplayer](https://mvnrepository.com/artifact/dev.arbjerg/lavaplayer)/[lavalink](https://maven.lavalink.dev/#/releases/dev/lavalink/youtube/common) versions. I will try to update this automatically in the future.
## Easy deployment via docker
Additionally, i thought a corresponding docker image would make things better:
The image can be found on [dockerhub](https://hub.docker.com/repository/docker/chrisb09/jmusicbot/general)
Docker-compose:
```yaml
version: '2.2'
services:
jmusicbot:
image: chrisb09/jmusicbot:latest
container_name: jmusicbot
restart: unless-stopped
volumes:
- ./config:/jmb/config
```
although, obviously you should change `./config` to whatever path is right for your setup.
Source code for the docker image is also on [Github](https://github.com/chrisb09/jmb-container).
## YouTube-Login
Obviously you still need to log in if you want to use youtube properly, hence you need to enable this in the config.
If you are using a pre-existing config, simply add:
```
/ If you set this to true, the bot will use a Google account to play YouTube tracks.
// This is only needed if you are experiencing issues with YouTube playback.
// Once enabled, instructions for login will be written to the console and DMs.
// DO NOT use your main Google account! Use an alternative account.
youtubeoauth2=true
```
If you start with a clean slate this line should already be present, albeit with `false` being the default.
As the author of the PR reiterates multiple times, do not use your main google account as using your account for a bot is most certainly against the ToS and thus you are endangering said account.
To add the account you simply have to follow the very basic instructions printed either in the console or sent to you from the bot via discord after you have started it, open the linked google page and paste the code.
# JMusicBot
[![Downloads](https://img.shields.io/github/downloads/jagrosh/MusicBot/total.svg)](https://github.com/jagrosh/MusicBot/releases/latest)
+8 -9
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.jagrosh</groupId>
<artifactId>JMusicBot</artifactId>
<version>Snapshot</version>
<version>0.4.5</version>
<packaging>jar</packaging>
<repositories>
@@ -44,23 +44,22 @@
<artifactId>JDA</artifactId>
<version>4.4.1_353</version>
</dependency>
<dependency>
<groupId>com.jagrosh</groupId>
<artifactId>jda-utilities</artifactId>
<version>3.0.5</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.github.Nagami-Yukki</groupId>
<artifactId>JDA-Utilities</artifactId>
<version>1.0</version>
</dependency>
<!-- Music Dependencies -->
<dependency>
<groupId>dev.arbjerg</groupId>
<artifactId>lavaplayer</artifactId>
<version>2.2.1</version>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>dev.lavalink.youtube</groupId>
<artifactId>common</artifactId>
<version>1.5.1</version>
<version>1.10.2</version>
</dependency>
<dependency>
<groupId>com.github.jagrosh</groupId>
@@ -26,6 +26,7 @@ import com.jagrosh.jmusicbot.gui.GUI;
import com.jagrosh.jmusicbot.playlist.PlaylistLoader;
import com.jagrosh.jmusicbot.settings.SettingsManager;
import java.util.Objects;
import com.jagrosh.jmusicbot.utils.YoutubeOauth2TokenHandler;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.entities.Guild;
@@ -44,6 +45,7 @@ public class Bot
private final PlaylistLoader playlists;
private final NowplayingHandler nowplaying;
private final AloneInVoiceHandler aloneInVoiceHandler;
private final YoutubeOauth2TokenHandler youTubeOauth2TokenHandler;
private boolean shuttingDown = false;
private JDA jda;
@@ -56,6 +58,8 @@ public class Bot
this.settings = settings;
this.playlists = new PlaylistLoader(config);
this.threadpool = Executors.newSingleThreadScheduledExecutor();
this.youTubeOauth2TokenHandler = new YoutubeOauth2TokenHandler();
this.youTubeOauth2TokenHandler.init();
this.players = new PlayerManager(this);
this.players.init();
this.nowplaying = new NowplayingHandler(this);
@@ -103,6 +107,11 @@ public class Bot
{
return aloneInVoiceHandler;
}
public YoutubeOauth2TokenHandler getYouTubeOauth2Handler()
{
return youTubeOauth2TokenHandler;
}
public JDA getJDA()
{
@@ -42,7 +42,7 @@ public class BotConfig
private String token, prefix, altprefix, helpWord, playlistsFolder, logLevel,
successEmoji, warningEmoji, errorEmoji, loadingEmoji, searchingEmoji,
evalEngine;
private boolean stayInChannel, songInGame, npImages, updatealerts, useEval, dbots;
private boolean youtubeOauth2, stayInChannel, songInGame, npImages, updatealerts, useEval, dbots;
private long owner, maxSeconds, aloneTimeUntilStop;
private int maxYTPlaylistPages;
private double skipratio;
@@ -84,6 +84,7 @@ public class BotConfig
searchingEmoji = config.getString("searching");
game = OtherUtil.parseGame(config.getString("game"));
status = OtherUtil.parseStatus(config.getString("status"));
youtubeOauth2 = config.getBoolean("youtubeoauth2");
stayInChannel = config.getBoolean("stayinchannel");
songInGame = config.getBoolean("songinstatus");
npImages = config.getBoolean("npimages");
@@ -293,6 +294,11 @@ public class BotConfig
return helpWord;
}
public boolean useYoutubeOauth2()
{
return youtubeOauth2;
}
public boolean getStay()
{
return stayInChannel;
@@ -17,8 +17,10 @@ package com.jagrosh.jmusicbot;
import com.jagrosh.jmusicbot.utils.OtherUtil;
import java.util.concurrent.TimeUnit;
import com.jagrosh.jmusicbot.utils.YoutubeOauth2TokenHandler;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.PrivateChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.VoiceChannel;
import net.dv8tion.jda.api.events.ReadyEvent;
@@ -85,6 +87,22 @@ public class Listener extends ListenerAdapter
catch(Exception ignored) {} // ignored
}, 0, 24, TimeUnit.HOURS);
}
if (bot.getConfig().useYoutubeOauth2())
{
YoutubeOauth2TokenHandler.Data data = bot.getYouTubeOauth2Handler().getData();
if (data != null)
{
PrivateChannel channel = bot.getJDA().openPrivateChannelById(bot.getConfig().getOwnerId()).complete();
channel
.sendMessage(
"# DO NOT AUTHORISE THIS WITH YOUR MAIN GOOGLE ACCOUNT!!!\n"
+ "## Create or use an alternative/burner Google account!\n"
+ "To give JMusicBot access to your Google account, go to "
+ data.getAuthorisationUrl()
+ " and enter the code **" + data.getCode() + "**")
.queue();
}
}
}
@Override
@@ -41,6 +41,7 @@ import net.dv8tion.jda.api.audio.AudioSendHandler;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
@@ -53,6 +54,7 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
public final static String PAUSE_EMOJI = "\u23F8"; // ⏸
public final static String STOP_EMOJI = "\u23F9"; // ⏹
private final static Logger LOGGER = LoggerFactory.getLogger(AudioHandler.class);
private final List<AudioTrack> defaultQueue = new LinkedList<>();
private final Set<String> votes = new HashSet<>();
@@ -202,8 +204,20 @@ public class AudioHandler extends AudioEventAdapter implements AudioSendHandler
}
@Override
public void onTrackException(AudioPlayer player, AudioTrack track, FriendlyException exception) {
LoggerFactory.getLogger("AudioHandler").error("Track " + track.getIdentifier() + " has failed to play", exception);
public void onTrackException(AudioPlayer player, AudioTrack track, FriendlyException exception)
{
if (
exception.getMessage().equals("Sign in to confirm you're not a bot")
|| exception.getMessage().equals("Please sign in")
)
LOGGER.error(
"Track {} has failed to play: {}"
+ "You will need to sign in to Google to play YouTube tracks. More info: https://jmusicbot.com/youtube-oauth2",
track.getIdentifier(),
exception.getMessage()
);
else
LOGGER.error("Track {} has failed to play", track.getIdentifier(), exception);
}
@Override
@@ -17,6 +17,7 @@ package com.jagrosh.jmusicbot.audio;
import com.dunctebot.sourcemanagers.DuncteBotSources;
import com.jagrosh.jmusicbot.Bot;
import com.jagrosh.jmusicbot.utils.OtherUtil;
import com.sedmelluq.discord.lavaplayer.container.MediaContainerRegistry;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
@@ -31,6 +32,11 @@ import com.sedmelluq.discord.lavaplayer.source.twitch.TwitchStreamAudioSourceMan
import com.sedmelluq.discord.lavaplayer.source.vimeo.VimeoAudioSourceManager;
import dev.lavalink.youtube.YoutubeAudioSourceManager;
import net.dv8tion.jda.api.entities.Guild;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
/**
*
@@ -38,6 +44,7 @@ import net.dv8tion.jda.api.entities.Guild;
*/
public class PlayerManager extends DefaultAudioPlayerManager
{
private final static Logger LOGGER = LoggerFactory.getLogger(PlayerManager.class);
private final Bot bot;
public PlayerManager(Bot bot)
@@ -49,8 +56,7 @@ public class PlayerManager extends DefaultAudioPlayerManager
{
TransformativeAudioSourceManager.createTransforms(bot.getConfig().getTransforms()).forEach(t -> registerSourceManager(t));
YoutubeAudioSourceManager yt = new YoutubeAudioSourceManager(true);
yt.setPlaylistPageCount(bot.getConfig().getMaxYTPlaylistPages());
YoutubeAudioSourceManager yt = setupYoutubeAudioSourceManager();
registerSourceManager(yt);
registerSourceManager(SoundCloudAudioSourceManager.createDefault());
@@ -66,7 +72,42 @@ public class PlayerManager extends DefaultAudioPlayerManager
DuncteBotSources.registerAll(this, "en-US");
}
private YoutubeAudioSourceManager setupYoutubeAudioSourceManager()
{
YoutubeAudioSourceManager yt = new YoutubeAudioSourceManager(true);
yt.setPlaylistPageCount(bot.getConfig().getMaxYTPlaylistPages());
// OAuth2 setup
if (bot.getConfig().useYoutubeOauth2())
{
String token = null;
try
{
token = Files.readString(OtherUtil.getPath("youtubetoken.txt"));
}
catch (NoSuchFileException e)
{
/* ignored */
}
catch (IOException e)
{
LOGGER.warn("Failed to read YouTube OAuth2 token file: {}", e.getMessage());
return yt;
}
LOGGER.debug("Read YouTube OAuth2 refresh token from youtubetoken.txt");
try
{
yt.useOauth2(token, false);
}
catch (Exception e)
{
LOGGER.warn("Failed to authorise with YouTube. If this issue persists, delete the youtubetoken.txt file to reauthorise.", e);
}
}
return yt;
}
public Bot getBot()
{
return bot;
@@ -94,7 +94,7 @@ public class FormatUtil {
public static String listOfRoles(List<Role> list, String query)
{
String out = " Multiple text channels found matching \""+query+"\":";
String out = " Multiple roles 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)
@@ -0,0 +1,91 @@
package com.jagrosh.jmusicbot.utils;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.turbo.TurboFilter;
import ch.qos.logback.core.spi.FilterReply;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import java.nio.file.Files;
/**
* A logback turbo filter, used retrieve the YouTube OAuth2 refresh token that gets logged once authorized with YouTube.
*
* @author Michaili K. <git@michaili.dev>
*/
public class YoutubeOauth2TokenHandler extends TurboFilter {
public final static org.slf4j.Logger LOGGER = LoggerFactory.getLogger(YoutubeOauth2TokenHandler.class);
private Data data;
public void init()
{
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
context.addTurboFilter(this);
}
public Data getData()
{
return data;
}
@Override
public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t)
{
if (!logger.getName().equals("dev.lavalink.youtube.http.YoutubeOauth2Handler"))
return FilterReply.NEUTRAL;
if (format.equals("OAUTH INTEGRATION: To give youtube-source access to your account, go to {} and enter code {}"))
{
this.data = new Data((String) params[0], (String) params[1]);
return FilterReply.NEUTRAL;
}
if (format.equals("OAUTH INTEGRATION: Token retrieved successfully. Store your refresh token as this can be reused. ({})"))
{
LOGGER.info(
"Authorization successful & retrieved token! Storing the token in {}",
OtherUtil.getPath("youtubetoken.txt").toAbsolutePath()
);
try
{
Files.write(OtherUtil.getPath("youtubetoken.txt"), params[0].toString().getBytes());
}
catch (Exception e)
{
LOGGER.error(
"Failed to write the YouTube OAuth2 refresh token to storage! You will need to authorize again on the next reboot",
e
);
}
return FilterReply.DENY;
}
return FilterReply.NEUTRAL;
}
public static class Data
{
private final String authorisationUrl;
private final String code;
private Data(String authorisationUrl, String code)
{
this.authorisationUrl = authorisationUrl;
this.code = code;
}
public String getCode()
{
return code;
}
public String getAuthorisationUrl()
{
return authorisationUrl;
}
}
}
+8
View File
@@ -48,6 +48,14 @@ game = "DEFAULT"
status = ONLINE
// If you set this to true, the bot will use a Google account to play YouTube tracks.
// This is only needed if you are experiencing issues with YouTube playback.
// Once enabled, instructions for login will be written to the console and DMs.
// DO NOT use your main Google account! Use an alternative account.
youtubeoauth2=false
// If you set this to true, the bot will list the title of the song it is currently playing in its
// "Playing" status. Note that this will ONLY work if the bot is playing music on ONE guild;
// if the bot is playing on multiple guilds, this will not work.