Skip to content
Open

Essa #1828

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ A cross-platform Discord music bot with a clean interface, and that is easy to s
* Smooth playback
* Server-specific setup for the "DJ" role that can moderate the music
* Clean and beautiful menus
* Supports many sites, including Youtube, Soundcloud, and more
* Supports many sites, including Youtube (or Invidious), Soundcloud, and more
* Supports many online radio/streams
* Supports local files
* Playlist support (both web/youtube, and local)

## Supported sources and formats
JMusicBot supports all sources and formats supported by [lavaplayer](https://github.com/sedmelluq/lavaplayer#supported-formats):
### Sources
* YouTube
* YouTube (or Invidious)
* SoundCloud
* Bandcamp
* Vimeo
Expand All @@ -53,6 +53,17 @@ JMusicBot supports all sources and formats supported by [lavaplayer](https://git
## Setup
Please see the [Setup Page](https://jmusicbot.com/setup) to run this bot yourself!

### Using Invidious
If YouTube links fail to load you can configure the bot to use [Invidious](https://github.com/iv-org/invidious) instances.
Add an `invidious` section to your `config.txt` with a list of instance URLs:

```
invidious {
instances = [ "https://yewtu.be", "https://piped.video" ]
}
```
The bot will try each instance in order and fall back when one is unavailable.

## Questions/Suggestions/Bug Reports
**Please read the [Issues List](https://github.com/jagrosh/MusicBot/issues) before suggesting a feature**. If you have a question, need troubleshooting help, or want to brainstorm a new feature, please start a [Discussion](https://github.com/jagrosh/MusicBot/discussions). If you'd like to suggest a feature or report a reproducible bug, please open an [Issue](https://github.com/jagrosh/MusicBot/issues) on this repository. 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)!

Expand Down
19 changes: 18 additions & 1 deletion src/main/java/com/jagrosh/jmusicbot/BotConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class BotConfig
private double skipratio;
private OnlineStatus status;
private Activity game;
private Config aliases, transforms;
private Config aliases, transforms, invidious;

private boolean valid = false;

Expand Down Expand Up @@ -97,6 +97,11 @@ public void load()
playlistsFolder = config.getString("playlistsfolder");
aliases = config.getConfig("aliases");
transforms = config.getConfig("transforms");
try {
invidious = config.getConfig("invidious");
} catch(ConfigException.Missing e) {
invidious = ConfigFactory.empty();
}
skipratio = config.getDouble("skipratio");
dbots = owner == 113156185389092864L;

Expand Down Expand Up @@ -381,4 +386,16 @@ public Config getTransforms()
{
return transforms;
}

public boolean useInvidious()
{
return invidious != null && invidious.hasPath("instances") && !invidious.getStringList("instances").isEmpty();
}

public java.util.List<String> getInvidiousInstances()
{
if(useInvidious())
return invidious.getStringList("instances");
return java.util.Collections.emptyList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.jagrosh.jmusicbot.audio;

import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.track.AudioItem;
import com.sedmelluq.discord.lavaplayer.track.AudioReference;
import dev.lavalink.youtube.YoutubeAudioSourceManager;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Audio source manager that loads YouTube links through an Invidious instance.
*/
public class InvidiousAudioSourceManager extends YoutubeAudioSourceManager {
private final List<String> instances;
private int index = 0;
private static final Pattern YT_DOMAIN =
Pattern.compile("https?://(?:www\\.)?(?:youtube\\.com|youtu\\.be)(/.*)");

public InvidiousAudioSourceManager(List<String> instances) {
super(true);
this.instances = instances;
}

@Override
public AudioItem loadItem(AudioPlayerManager apm, AudioReference ar) {
if (ar.identifier == null)
return null;
for (int i = 0; i < instances.size(); i++) {
String url = convertToInstance(ar.identifier, getCurrentInstance());
try {
AudioItem item = super.loadItem(apm, new AudioReference(url, ar.title));
if (item != null)
return item;
} catch (Exception ex) {
rotateInstance();
}
}
return null;
}

static String convertToInstance(String url, String instance) {
Matcher m = YT_DOMAIN.matcher(url);
String domain = instance.endsWith("/") ? instance.substring(0, instance.length()-1) : instance;
if (m.find())
return "https://" + domain + m.group(1);
return url.replaceFirst("https?://[^/]+", "https://" + domain);
}

synchronized String getCurrentInstance() {
return instances.get(index);
}

synchronized void rotateInstance() {
index = (index + 1) % instances.size();
}
}
14 changes: 11 additions & 3 deletions src/main/java/com/jagrosh/jmusicbot/audio/PlayerManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.sedmelluq.discord.lavaplayer.source.twitch.TwitchStreamAudioSourceManager;
import com.sedmelluq.discord.lavaplayer.source.vimeo.VimeoAudioSourceManager;
import dev.lavalink.youtube.YoutubeAudioSourceManager;
import com.jagrosh.jmusicbot.audio.InvidiousAudioSourceManager;
import net.dv8tion.jda.api.entities.Guild;

/**
Expand All @@ -49,9 +50,16 @@ public void init()
{
TransformativeAudioSourceManager.createTransforms(bot.getConfig().getTransforms()).forEach(t -> registerSourceManager(t));

YoutubeAudioSourceManager yt = new YoutubeAudioSourceManager(true);
yt.setPlaylistPageCount(bot.getConfig().getMaxYTPlaylistPages());
registerSourceManager(yt);
if(bot.getConfig().useInvidious())
{
registerSourceManager(new InvidiousAudioSourceManager(bot.getConfig().getInvidiousInstances()));
}
else
{
YoutubeAudioSourceManager yt = new YoutubeAudioSourceManager(true);
yt.setPlaylistPageCount(bot.getConfig().getMaxYTPlaylistPages());
registerSourceManager(yt);
}

registerSourceManager(SoundCloudAudioSourceManager.createDefault());
registerSourceManager(new BandcampAudioSourceManager());
Expand Down
11 changes: 11 additions & 0 deletions src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,17 @@ loglevel = info
transforms = {}


// Optional Invidious support for YouTube
// Provide a list of Invidious instance URLs to use instead of youtube.com
// Example:
// invidious {
// instances = [ "https://yewtu.be", "https://piped.video" ]
// }
invidious {
instances = []
}


// If you set this to true, it will enable the eval command for the bot owner. This command
// allows the bot owner to run arbitrary code from the bot's account.
//
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.jagrosh.jmusicbot;

import com.jagrosh.jmusicbot.audio.InvidiousAudioSourceManager;
import java.util.Arrays;
import org.junit.Test;
import static org.junit.Assert.*;

public class InvidiousAudioSourceManagerTest {
@Test
public void convertYoutubeLink() {
String result = InvidiousAudioSourceManager.convertToInstance(
"https://www.youtube.com/watch?v=abc", "yewtu.be");
assertEquals("https://yewtu.be/watch?v=abc", result);
}

@Test
public void rotateInstances() {
InvidiousAudioSourceManager mgr = new InvidiousAudioSourceManager(
Arrays.asList("a", "b"));
assertEquals("a", mgr.getCurrentInstance());
mgr.rotateInstance();
assertEquals("b", mgr.getCurrentInstance());
mgr.rotateInstance();
assertEquals("a", mgr.getCurrentInstance());
}
}