Skip to content
This repository has been archived by the owner on Nov 26, 2023. It is now read-only.

Commit

Permalink
Fix mixcloud playback
Browse files Browse the repository at this point in the history
  • Loading branch information
duncte123 committed Nov 22, 2023
1 parent bfe630a commit 5117ccb
Show file tree
Hide file tree
Showing 8 changed files with 566 additions and 25 deletions.
8 changes: 4 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ plugins {
}

project.group = "com.dunctebot"
project.version = "1.8.4"
project.version = "1.8.5"
val archivesBaseName = "sourcemanagers"

repositories {
Expand All @@ -43,11 +43,11 @@ dependencies {
// implementation(group = "com.github.duncte123", name = "lavaplayer", version = "be6e364")
compileOnly(group = "com.github.walkyst", name = "lavaplayer-fork", version = "1.4.2")

implementation("commons-io:commons-io:2.6")
implementation(group = "org.jsoup", name = "jsoup", version = "1.12.1")
implementation("commons-io:commons-io:2.7")
implementation(group = "org.jsoup", name = "jsoup", version = "1.15.3")
implementation(group = "com.google.code.findbugs", name = "jsr305", version = "3.0.2")

testImplementation(group = "com.github.walkyst", name = "lavaplayer-fork", version = "1.3.99.1")
testImplementation(group = "com.github.walkyst", name = "lavaplayer-fork", version = "1.4.2")
}

configure<JavaPluginExtension> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;

import java.io.DataInput;
import java.io.DataOutput;
Expand All @@ -41,16 +44,50 @@
import static com.dunctebot.sourcemanagers.Utils.urlEncode;

public class MixcloudAudioSourceManager extends AbstractDuncteBotHttpSource {
private static final String REQUEST_STRUCTURE = "audioLength\n" +
" name\n" +
private static final String GRAPHQL_AUDIO_REQUEST = "query PlayerHeroQuery(\n" +
" $lookup: CloudcastLookup!\n" +
") {\n" +
" cloudcast: cloudcastLookup(lookup: $lookup) {\n" +
" id\n" +
" name\n" +
" owner {\n" +
" ...AudioPageAvatar_user\n" +
" id\n" +
" }\n" +
" restrictedReason\n" +
" seekRestriction\n" +
" ...PlayButton_cloudcast\n" +
" }\n" +
"}\n" +
"\n" +
"fragment AudioPageAvatar_user on User {\n" +
" displayName\n" +
" username\n" +
"}\n" +
"\n" +
"fragment PlayButton_cloudcast on Cloudcast {\n" +
" restrictedReason\n" +
" owner {\n" +
" username\n" +
" displayName\n" +
" country\n" +
" username\n" +
" isSubscribedTo\n" +
" isViewer\n" +
" id\n" +
" }\n" +
" slug\n" +
" id\n" +
" isDraft\n" +
" isPlayable\n" +
" streamInfo {\n" +
" dashUrl\n" +
" hlsUrl\n" +
" url\n" +
" }";
" hlsUrl\n" +
" dashUrl\n" +
" url\n" +
" uuid\n" +
" }\n" +
" audioLength\n" +
" seekRestriction\n" +
"}\n";
private static final Pattern URL_REGEX = Pattern.compile("https?://(?:(?:www|beta|m)\\.)?mixcloud\\.com/([^/]+)/(?!stream|uploads|favorites|listens|playlists)([^/]+)/?");

@Override
Expand Down Expand Up @@ -89,6 +126,16 @@ private AudioItem loadItemOnce(AudioReference reference, Matcher matcher) throws
return AudioReference.NO_TRACK;
}

final JsonBrowser restrictedReason = trackInfo.get("restrictedReason");

if (!restrictedReason.isNull()) {
throw new FriendlyException(
"Playback of this track is restricted.",
FriendlyException.Severity.COMMON,
new Exception(restrictedReason.text())
);
}

final String title = trackInfo.get("name").text();
final long duration = trackInfo.get("audioLength").as(Long.class) * 1000;
final String uploader = trackInfo.get("owner").get("username").text(); // displayName
Expand All @@ -107,17 +154,23 @@ private AudioItem loadItemOnce(AudioReference reference, Matcher matcher) throws
}

protected JsonBrowser extractTrackInfoGraphQl(String username, String slug) throws IOException {
final String slugFormatted = slug == null ? "" : String.format(", slug: \"%s\"", slug);
final String query = String.format(
"{\n cloudcastLookup(lookup: {username: \"%s\"%s}) {\n %s\n }\n}",
username,
slugFormatted,
REQUEST_STRUCTURE
);
final String encodedQuery = urlEncode(query);
final HttpGet httpGet = new HttpGet("https://www.mixcloud.com/graphql?query=" + encodedQuery);
final var body = JsonBrowser.newMap();

body.put("query", GRAPHQL_AUDIO_REQUEST);

final var variables = JsonBrowser.newMap();

variables.put("lookup", new MixcloudLookup(
slug, username
));

body.put("variables", variables);

final HttpPost httpPost = new HttpPost("https://app.mixcloud.com/graphql");

httpPost.setEntity(new StringEntity(body.text(), ContentType.APPLICATION_JSON));

try (final CloseableHttpResponse res = getHttpInterface().execute(httpGet)) {
try (final CloseableHttpResponse res = getHttpInterface().execute(httpPost)) {
final int statusCode = res.getStatusLine().getStatusCode();

if (statusCode != 200) {
Expand All @@ -129,7 +182,7 @@ protected JsonBrowser extractTrackInfoGraphQl(String username, String slug) thro
}

final String content = IOUtils.toString(res.getEntity().getContent(), StandardCharsets.UTF_8);
final JsonBrowser json = JsonBrowser.parse(content).get("data").get("cloudcastLookup");
final JsonBrowser json = JsonBrowser.parse(content).get("data").get("cloudcast");

if (json.get("streamInfo").isNull()) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.sedmelluq.discord.lavaplayer.tools.ExceptionTools;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.tools.Units;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;

import java.io.IOException;
Expand Down Expand Up @@ -62,6 +63,11 @@ public String getPlaybackUrl() {
}
}

@Override
protected AudioTrack makeShallowClone() {
return new MixcloudAudioTrack(trackInfo, getSourceManager());
}

@Override
public MixcloudAudioSourceManager getSourceManager() {
return (MixcloudAudioSourceManager) super.getSourceManager();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2023 Duncan "duncte123" Sterken
*
* 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.dunctebot.sourcemanagers.mixcloud;

public class MixcloudLookup {
private String slug;
private String username;

public MixcloudLookup(String slug, String username) {
this.slug = slug;
this.username = username;
}

public String getSlug() {
return slug;
}

public void setSlug(String slug) {
this.slug = slug;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}
}
16 changes: 13 additions & 3 deletions src/test/java/MixcloudTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,24 @@

import com.dunctebot.sourcemanagers.mixcloud.MixcloudAudioSourceManager;
import com.dunctebot.sourcemanagers.mixcloud.MixcloudAudioTrack;
import com.sedmelluq.discord.lavaplayer.track.AudioItem;
import com.sedmelluq.discord.lavaplayer.track.AudioReference;

public class MixcloudTest {
public static void main(String[] args) {
final var url = "https://www.mixcloud.com/jordy-boesten2/the-egotripper-lets-walk-to-my-house-mix-259/";
// System.out.println(MixcloudAudioSourceManager.GRAPHQL_AUDIO_REQUEST);

// final var url = "https://www.mixcloud.com/jordy-boesten2/the-egotripper-lets-walk-to-my-house-mix-259/";
final var url = "https://www.mixcloud.com/Hirockn/the-100-best-tracks-2020-hip-hop-rb-pops-etc-the-weeknd-dababy-dua-lipa-juice-wrld-etc/";
final var mnrg = new MixcloudAudioSourceManager();
final var track = (MixcloudAudioTrack) mnrg.loadItem(null, new AudioReference(url, null));
final var playbackUrl = track.getPlaybackUrl();
final AudioItem track = mnrg.loadItem(null, new AudioReference(url, null));

if (track.equals(AudioReference.NO_TRACK)) {
return;
}

final var mixcloudTrack = (MixcloudAudioTrack) track;
final var playbackUrl = mixcloudTrack.getPlaybackUrl();

System.out.println(playbackUrl);
}
Expand Down
Loading

0 comments on commit 5117ccb

Please sign in to comment.