Skip to content

Commit 373ea70

Browse files
committed
Tumblr support works
1 parent 702e5aa commit 373ea70

6 files changed

Lines changed: 105 additions & 18 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Adding support for the following sources:
1313
- streamDeckAudio files
1414
- These files are only accepted over HTTP currently
1515
- Pixeldrain.com
16+
- Tumblr.com (when it does not throw a 403 your way)
1617

1718
## Lavalink version compatibility
1819

@@ -64,7 +65,7 @@ plugins:
6465
mixcloud: true # mixcloud.com
6566
soundgasm: true # soundgasm.net
6667
pixeldrain: true # pixeldrain.com
67-
tumblr: true # tumblr.com, requires an app to be configured with oauth2 support
68+
tumblr: false # tumblr.com, requires an app to be configured with oauth2 support
6869
```
6970
7071
## development

source-managers/src/main/java/com/dunctebot/sourcemanagers/Utils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import java.nio.charset.Charset;
2424

2525
public class Utils {
26-
public static final String USER_AGENT = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/114.0";
26+
public static final String USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0";
2727

2828
public static String urlDecode(String in) {
2929
return URLDecoder.decode(in, Charset.defaultCharset());

source-managers/src/main/java/com/dunctebot/sourcemanagers/ocremix/OCRemixAudioTrack.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
package com.dunctebot.sourcemanagers.ocremix;
2020

2121
import com.dunctebot.sourcemanagers.AbstractDuncteBotHttpSource;
22-
import com.dunctebot.sourcemanagers.IWillUseIdentifierInstead;
2322
import com.dunctebot.sourcemanagers.Mp3Track;
2423
import com.sedmelluq.discord.lavaplayer.tools.io.HttpInterface;
2524
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;

source-managers/src/main/java/com/dunctebot/sourcemanagers/tumblr/TumblrAudioSourceManager.java

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import com.dunctebot.sourcemanagers.AbstractDuncteBotHttpSource;
1111
import com.dunctebot.sourcemanagers.tumblr.audio.TumblrBasePostAudioTrack;
12+
import com.dunctebot.sourcemanagers.tumblr.audio.TumblrMp3AudioTrack;
1213
import com.dunctebot.sourcemanagers.tumblr.audio.TumblrMpegAudioTrack;
1314
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
1415
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
@@ -24,6 +25,8 @@
2425
import org.apache.http.client.methods.HttpPost;
2526
import org.apache.http.entity.ContentType;
2627
import org.apache.http.entity.StringEntity;
28+
import org.slf4j.Logger;
29+
import org.slf4j.LoggerFactory;
2730

2831
import java.io.DataInput;
2932
import java.io.DataOutput;
@@ -32,15 +35,21 @@
3235
import java.util.List;
3336
import java.util.regex.Pattern;
3437

38+
import static com.dunctebot.sourcemanagers.Utils.USER_AGENT;
39+
3540
public class TumblrAudioSourceManager extends AbstractDuncteBotHttpSource {
3641
private static final Pattern NORMAL_POST_PATTERN = Pattern.compile("https:\\/\\/(?:www\\.)?tumblr\\.com\\/(?<username>[^\\/]+)\\/(?<postId>[^\\/]+)\\/?.*");
3742
private static final Pattern BLOG_SUB_PATTERN = Pattern.compile("https:\\/\\/(?<username>[^\\.]+)\\.tumblr\\.com\\/post\\/(?<postId>[^\\/]+)\\/?.*");
43+
private static final Logger log = LoggerFactory.getLogger(TumblrAudioSourceManager.class);
3844

39-
// TODO: https://tmblr.co/ZWMt9uiVE9gHKi00
45+
// TODO: https://tmblr.co/ZWMt9uiVE9gHKi00 (when I feel like it tbh, nobody uses these links)
4046

4147
private final String oauthConsumerKey;
4248
private final String oauthSecretKey;
4349

50+
private long tokenExpiresAt = -1;
51+
private String accessToken = null;
52+
4453
public TumblrAudioSourceManager(String consumerKey, String secretKey) {
4554
this.oauthConsumerKey = consumerKey;
4655
this.oauthSecretKey = secretKey;
@@ -101,12 +110,15 @@ public void encodeTrack(AudioTrack track, DataOutput output) throws IOException
101110
public AudioTrack decodeTrack(AudioTrackInfo trackInfo, DataInput input) throws IOException {
102111
final var mediaUrl = input.readUTF();
103112

104-
if (trackInfo.identifier.endsWith("audio/mpeg")) {
113+
if (trackInfo.uri.endsWith("audio/mpeg")) {
114+
return new TumblrMp3AudioTrack(trackInfo, this, mediaUrl);
115+
}
116+
117+
if (trackInfo.uri.endsWith("video/mp4")) {
105118
return new TumblrMpegAudioTrack(trackInfo, this, mediaUrl);
106119
}
107120

108-
// TODO: this error is wrong
109-
throw new FriendlyException("Unknown post type encountered while decoding tumblr track", FriendlyException.Severity.COMMON, null);
121+
throw new FriendlyException("Unknown media type encountered whilst trying to decode tumblr track", FriendlyException.Severity.COMMON, null);
110122
}
111123

112124
public TumblrBasePostAudioTrack fetchPostData(String username, String postId) throws Exception {
@@ -149,22 +161,22 @@ public TumblrBasePostAudioTrack postToTrack(JsonBrowser post, String postUrl) {
149161
throw new FriendlyException("Provider not supported: " + ci.get("provider").text(), FriendlyException.Severity.COMMON, null);
150162
}
151163

152-
final var creatorName = post.get("blog").get("title").text();
164+
final var creatorName = getBlogName(post);
153165
final var artwork = post.get("blog").get("avatar").index(0).get("url").text();
154166

155167
final var audioType = ci.get("media").get("type").text();
156168
final var audioUrl = ci.get("media").get("url").text();
157169
final var audioTitle = ci.get("title").textOrDefault("Tumblr Audio by " + creatorName);
158170

159171
if (audioType.equals("audio/mpeg")) {
160-
return new TumblrMpegAudioTrack(
172+
return new TumblrMp3AudioTrack(
161173
new AudioTrackInfo(
162174
audioTitle,
163175
creatorName,
164176
Units.CONTENT_LENGTH_UNKNOWN,
165-
postUrl + "?dbextra=" + audioType,
166-
false,
167177
postUrl,
178+
false,
179+
postUrl + "?dbextra=" + audioType,
168180
artwork,
169181
null
170182
),
@@ -173,7 +185,32 @@ public TumblrBasePostAudioTrack postToTrack(JsonBrowser post, String postUrl) {
173185
);
174186
}
175187
} else if ("video".equals(ci.get("type").text())) {
176-
// TODO
188+
if (!"tumblr".equals(ci.get("provider").text())) {
189+
throw new FriendlyException("Provider not supported: " + ci.get("provider").text(), FriendlyException.Severity.COMMON, null);
190+
}
191+
192+
final var creatorName = getBlogName(post);
193+
final var artwork = post.get("blog").get("avatar").index(0).get("url").text();
194+
195+
final var videoType = ci.get("media").get("type").text();
196+
final var videoUrl = ci.get("media").get("url").text();
197+
198+
if (videoType.equals("video/mp4")) {
199+
return new TumblrMpegAudioTrack(
200+
new AudioTrackInfo(
201+
"Tumblr Video by " + creatorName,
202+
creatorName,
203+
Units.CONTENT_LENGTH_UNKNOWN,
204+
postUrl,
205+
false,
206+
postUrl + "?dbextra=" + videoType,
207+
artwork,
208+
null
209+
),
210+
this,
211+
videoUrl
212+
);
213+
}
177214
}
178215
}
179216

@@ -192,18 +229,33 @@ public JsonBrowser fetchNPFData(String username, String postId) throws Exception
192229
final var token = this.fetchOAuth2Token();
193230

194231
httpGet.addHeader("Authorization", "Bearer " + token);
232+
httpGet.addHeader("Accept", "application/json");
233+
httpGet.setHeader("User-Agent", USER_AGENT);
195234

196235
try (final CloseableHttpResponse res = getHttpInterface().execute(httpGet)) {
197236
final String content = IOUtils.toString(res.getEntity().getContent(), StandardCharsets.UTF_8);
198237

238+
System.out.println(content);
239+
240+
final int statusCode = res.getStatusLine().getStatusCode();
241+
242+
if (statusCode != 200) {
243+
throw new IOException("Tumblr api request failed: " + statusCode);
244+
}
245+
199246
return JsonBrowser.parse(content);
200247
}
201248
}
202249

203250
public String fetchOAuth2Token() throws Exception {
251+
if (System.currentTimeMillis() < this.tokenExpiresAt) {
252+
return this.accessToken;
253+
}
254+
204255
final var httpPost = new HttpPost("https://api.tumblr.com/v2/oauth2/token");
205256

206257
httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
258+
httpPost.setHeader("User-Agent", USER_AGENT);
207259

208260
final var body = String.join("&", List.of(
209261
// Thank you for not documenting this LMAO
@@ -217,9 +269,32 @@ public String fetchOAuth2Token() throws Exception {
217269
);
218270

219271
try (final CloseableHttpResponse res = getHttpInterface().execute(httpPost)) {
272+
final int statusCode = res.getStatusLine().getStatusCode();
273+
274+
if (statusCode != 200) {
275+
throw new IOException("Invalid status for fetching tumblr access token: " + statusCode);
276+
}
277+
220278
final String content = IOUtils.toString(res.getEntity().getContent(), StandardCharsets.UTF_8);
221279

222-
return JsonBrowser.parse(content).get("access_token").text();
280+
System.out.println(content);
281+
282+
final var json = JsonBrowser.parse(content);
283+
this.accessToken = json.get("access_token").text();
284+
// expires_in is in seconds
285+
this.tokenExpiresAt = System.currentTimeMillis() + (json.get("expires_in").asLong(0L) * 1000L);
286+
287+
return this.accessToken;
223288
}
224289
}
290+
291+
private static String getBlogName(JsonBrowser post) {
292+
final var blogTitle = post.get("blog").get("title").safeText();
293+
294+
if (blogTitle.isBlank()) {
295+
return post.get("blog").get("name").text();
296+
}
297+
298+
return blogTitle;
299+
}
225300
}

source-managers/src/main/java/com/dunctebot/sourcemanagers/tumblr/audio/TumblrMp3AudioTrack.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,24 @@
22

33
import com.dunctebot.sourcemanagers.AbstractDuncteBotHttpSource;
44
import com.dunctebot.sourcemanagers.Mp3Track;
5-
import com.dunctebot.sourcemanagers.tumblr.TumblrPostType;
65
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
76

87
public class TumblrMp3AudioTrack extends Mp3Track implements TumblrBasePostAudioTrack {
9-
public TumblrMp3AudioTrack(AudioTrackInfo trackInfo, AbstractDuncteBotHttpSource manager) {
8+
private final String mediaUrl;
9+
10+
public TumblrMp3AudioTrack(AudioTrackInfo trackInfo, AbstractDuncteBotHttpSource manager, String mediaUrl) {
1011
super(trackInfo, manager);
12+
13+
this.mediaUrl = mediaUrl;
1114
}
1215

1316
@Override
1417
public String getMediaUrl() {
15-
return "";
18+
return this.mediaUrl;
19+
}
20+
21+
@Override
22+
public String getPlaybackUrl() {
23+
return this.getMediaUrl();
1624
}
1725
}

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@ public static void main(String[] args) throws Exception {
1111

1212
System.out.println("Token found " + token);
1313

14-
final var npfData = mngr.fetchPostData("pukicho", "801421495209476096");
14+
final var npfData = mngr.fetchNPFData("ectoblood", "809867644956213248");
1515

16-
System.out.println(npfData.getMediaUrl());
16+
System.out.println(npfData.text());
17+
18+
// final var audioTrack = mngr.fetchPostData("pukicho", "801421495209476096");
19+
20+
// System.out.println(audioTrack.getMediaUrl());
1721
}
1822
}

0 commit comments

Comments
 (0)