Skip to content

Commit 3676296

Browse files
committed
Add pixeldrain 'support'
1 parent a8762b1 commit 3676296

6 files changed

Lines changed: 187 additions & 3 deletions

File tree

plugin/src/main/java/com/dunctebot/lavalinkplugin/DuncteBotConfig.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public static class Sources {
2929
private boolean mixcloud = true;
3030
private boolean soundgasm = true;
3131
private boolean elgato = false;
32+
private boolean pixeldrain = false;
3233

3334
public boolean isGetyarn() {
3435
return getyarn;
@@ -109,5 +110,13 @@ public boolean isElgato() {
109110
public void setElgato(boolean elgato) {
110111
this.elgato = elgato;
111112
}
113+
114+
public boolean isPixeldrain() {
115+
return pixeldrain;
116+
}
117+
118+
public void setPixeldrain(boolean pixeldrain) {
119+
this.pixeldrain = pixeldrain;
120+
}
112121
}
113122
}

plugin/src/main/java/com/dunctebot/lavalinkplugin/DuncteBotInjector.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.dunctebot.sourcemanagers.getyarn.GetyarnAudioSourceManager;
66
import com.dunctebot.sourcemanagers.mixcloud.MixcloudAudioSourceManager;
77
import com.dunctebot.sourcemanagers.ocremix.OCRemixAudioSourceManager;
8+
import com.dunctebot.sourcemanagers.pixeldrain.PixeldrainAudioSourceManager;
89
import com.dunctebot.sourcemanagers.pornhub.PornHubAudioSourceManager;
910
import com.dunctebot.sourcemanagers.reddit.RedditAudioSourceManager;
1011
import com.dunctebot.sourcemanagers.soundgasm.SoundGasmAudioSourceManager;
@@ -89,6 +90,11 @@ public AudioPlayerManager configure(@NotNull AudioPlayerManager manager) {
8990
// manager.registerSourceManager(new StreamDeckAudioSourceManager());
9091
}
9192

93+
if (this.sourcesConfig.isPixeldrain()) {
94+
logger.info("Registering pixeldrain audio source manager");
95+
manager.registerSourceManager(new PixeldrainAudioSourceManager());
96+
}
97+
9298
return manager;
9399
}
94100
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.dunctebot.sourcemanagers.pixeldrain;
2+
3+
import com.dunctebot.sourcemanagers.AbstractDuncteBotHttpSource;
4+
import com.dunctebot.sourcemanagers.Mp3Track;
5+
import com.sedmelluq.discord.lavaplayer.container.wav.WavAudioTrack;
6+
import com.sedmelluq.discord.lavaplayer.tools.io.SeekableInputStream;
7+
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
8+
import com.sedmelluq.discord.lavaplayer.track.InternalAudioTrack;
9+
10+
public class PixelDrainAudioTrack extends Mp3Track {
11+
public PixelDrainAudioTrack(AudioTrackInfo trackInfo, AbstractDuncteBotHttpSource manager) {
12+
super(trackInfo, manager);
13+
}
14+
15+
@Override
16+
protected InternalAudioTrack createAudioTrack(AudioTrackInfo trackInfo, SeekableInputStream stream) {
17+
return new WavAudioTrack(trackInfo, stream);
18+
}
19+
20+
@Override
21+
public String getPlaybackUrl() {
22+
return String.format(PixeldrainAudioSourceManager.AUDIO_TEMPLATE, this.trackInfo.identifier);
23+
}
24+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package com.dunctebot.sourcemanagers.pixeldrain;
2+
3+
import com.dunctebot.sourcemanagers.AbstractDuncteBotHttpSource;
4+
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
5+
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
6+
import com.sedmelluq.discord.lavaplayer.tools.Units;
7+
import com.sedmelluq.discord.lavaplayer.track.AudioItem;
8+
import com.sedmelluq.discord.lavaplayer.track.AudioReference;
9+
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
10+
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
11+
import org.apache.commons.io.IOUtils;
12+
import org.apache.http.client.methods.CloseableHttpResponse;
13+
import org.apache.http.client.methods.HttpGet;
14+
import org.jsoup.Jsoup;
15+
import org.jsoup.nodes.Document;
16+
17+
import java.io.DataInput;
18+
import java.io.DataOutput;
19+
import java.io.IOException;
20+
import java.nio.charset.StandardCharsets;
21+
22+
public class PixeldrainAudioSourceManager extends AbstractDuncteBotHttpSource {
23+
private static final String PIXELDRAIN_LOOKUP_BASE = "https://pixeldrain.com/u/";
24+
25+
/* package */ static final String AUDIO_TEMPLATE = "https://pixeldrain.com/api/file/%s";
26+
private static final String THUMBNAIL_TEMPLATE = AUDIO_TEMPLATE + "/thumbnail";
27+
28+
@Override
29+
public String getSourceName() {
30+
return "pixeldrain";
31+
}
32+
33+
@Override
34+
public AudioItem loadItem(AudioPlayerManager manager, AudioReference reference) {
35+
final var id = reference.getIdentifier();
36+
37+
if (id.startsWith(PIXELDRAIN_LOOKUP_BASE)) {
38+
final var parts = id.split(PIXELDRAIN_LOOKUP_BASE);
39+
40+
if (parts.length < 2) {
41+
return null;
42+
}
43+
44+
final var identifier = parts[1];
45+
46+
try {
47+
final var trackInfo = downloadInfo(identifier);
48+
49+
return decodeTrack(trackInfo, null);
50+
} catch (IOException e) {
51+
throw new FriendlyException(
52+
"Could not download pixeldrain track info",
53+
FriendlyException.Severity.SUSPICIOUS,
54+
e
55+
);
56+
}
57+
}
58+
59+
return null;
60+
}
61+
62+
private AudioTrackInfo downloadInfo(String identifier) throws IOException {
63+
final var document = loadHtml(identifier);
64+
65+
if (document == null) {
66+
notAvailable();
67+
}
68+
69+
// System.out.println(document.select("meta[property]"));
70+
71+
final var title = document.selectFirst("meta[property='og:title']").attr("content");
72+
final var type = document.selectFirst("meta[property='og:type']").attr("content");
73+
74+
if (!"music.song".equals(type)) {
75+
throw new FriendlyException("Type " + type + " is currently not supported", FriendlyException.Severity.COMMON, null);
76+
}
77+
78+
System.out.println(type);
79+
System.out.println(title);
80+
81+
return new AudioTrackInfo(
82+
title,
83+
"Unknown artist",
84+
Units.CONTENT_LENGTH_UNKNOWN,
85+
identifier,
86+
false,
87+
PIXELDRAIN_LOOKUP_BASE + identifier,
88+
String.format(THUMBNAIL_TEMPLATE, identifier),
89+
null
90+
);
91+
}
92+
93+
private Document loadHtml(String identifier) throws IOException {
94+
final var httpGet = new HttpGet(PIXELDRAIN_LOOKUP_BASE + identifier);
95+
96+
try (final CloseableHttpResponse response = getHttpInterface().execute(httpGet)) {
97+
final int statusCode = response.getStatusLine().getStatusCode();
98+
99+
if (statusCode != 200) {
100+
if (statusCode == 404) {
101+
return null;
102+
}
103+
104+
throw new IOException("Unexpected status code for pixeldrain page response: " + statusCode);
105+
}
106+
107+
final var html = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
108+
109+
return Jsoup.parse(html);
110+
}
111+
}
112+
113+
@Override
114+
public boolean isTrackEncodable(AudioTrack track) {
115+
return false;
116+
}
117+
118+
@Override
119+
public void encodeTrack(AudioTrack track, DataOutput output) throws IOException {
120+
// Nothing to encode
121+
}
122+
123+
@Override
124+
public AudioTrack decodeTrack(AudioTrackInfo trackInfo, DataInput input) throws IOException {
125+
return new PixelDrainAudioTrack(trackInfo, this);
126+
}
127+
128+
private void notAvailable() {
129+
throw new FriendlyException("This item is not available", FriendlyException.Severity.COMMON, null);
130+
}
131+
}

source-managers/src/test/java/LocalPlaybackTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import com.dunctebot.sourcemanagers.elgato.streamdeck.StreamDeckAudioSourceManager;
2+
import com.dunctebot.sourcemanagers.pixeldrain.PixeldrainAudioSourceManager;
23
import com.sedmelluq.discord.lavaplayer.format.AudioDataFormat;
34
import com.sedmelluq.discord.lavaplayer.format.AudioPlayerInputStream;
45
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
@@ -15,7 +16,7 @@
1516

1617
public class LocalPlaybackTest {
1718
public static void main(String[] args) throws Exception {
18-
final var mngr = new StreamDeckAudioSourceManager();
19+
final var mngr = new PixeldrainAudioSourceManager();
1920

2021
AudioPlayerManager manager = new DefaultAudioPlayerManager();
2122

@@ -25,10 +26,10 @@ public static void main(String[] args) throws Exception {
2526

2627
AudioPlayer player = manager.createPlayer();
2728

28-
player.setVolume(35);
29+
player.setVolume(100);
2930

3031
manager.loadItem(
31-
"https://cdn.discordapp.com/attachments/340834322674089986/1242398908815118376/Fanfare_-_Show_Intro.streamDeckAudio?ex=664f0326&is=664db1a6&hm=9a4898f7301601b3bc14cfda4101aab0ed94cdfb5fe89d2a0917dc4e01514da6&",
32+
"https://pixeldrain.com/u/WUJkkH3F",
3233
new FunctionalResultHandler(item -> {
3334
player.playTrack(item);
3435
}, playlist -> {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import com.dunctebot.sourcemanagers.pixeldrain.PixeldrainAudioSourceManager;
2+
import com.sedmelluq.discord.lavaplayer.track.AudioReference;
3+
4+
public class PixeldrainTest {
5+
6+
public static void main(String[] args) {
7+
final var id1 = "https://pixeldrain.com/u/WUJkkH3F";
8+
final var mngr = new PixeldrainAudioSourceManager();
9+
final var res1 = mngr.loadItem(null, new AudioReference(id1, ""));
10+
11+
System.out.println(res1);
12+
}
13+
}

0 commit comments

Comments
 (0)