Skip to content

Commit becd12e

Browse files
committed
Allow for search in pornhub
1 parent f1d690d commit becd12e

File tree

6 files changed

+127
-12
lines changed

6 files changed

+127
-12
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Adding support for the following sources:
88
- getyarn.io
99
- Text To Speech (if prefixed with `speak:`)
1010
- TikTok (in beta, works on _most_ videos and **will** break all the time)
11-
- PornHub
11+
- PornHub (search by prefixing with `phsearch:`)
1212
- soundgasm
1313

1414
## Lavalink version compatibility

application.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ plugins:
3838
getyarn: false # www.getyarn.io
3939
clypit: false # www.clyp.it
4040
tts: false # speak:Words to speak
41-
pornhub: false # should be self-explanatory
41+
pornhub: true # should be self-explanatory
4242
reddit: false # should be self-explanatory
4343
ocremix: true # www.ocremix.org
4444
tiktok: true # tiktok.com
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.dunctebot.sourcemanagers.pornhub;
2+
3+
import com.sedmelluq.discord.lavaplayer.tools.Units;
4+
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
5+
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
6+
import org.jsoup.nodes.Element;
7+
8+
public final class PHHelpers {
9+
public static AudioTrack trackFromSearchElement(Element element, PornHubAudioSourceManager mngr) {
10+
final var info = infoFromSearchElement(element);
11+
return new PornHubAudioTrack(info, mngr);
12+
}
13+
14+
public static AudioTrackInfo infoFromSearchElement(Element element) {
15+
// TODO: parse min:sec duration
16+
// final var durText = element.getElementsByClass("duration").first().text();
17+
18+
// System.out.println(durText);
19+
20+
final String title = element.getElementsByClass("title").first().text();
21+
final String author = element.getElementsByClass("usernameWrap").first().text();
22+
final long duration = Units.CONTENT_LENGTH_UNKNOWN;
23+
final String identifier = element.attr("data-video-vkey");
24+
final String uri = "https://www.pornhub.com/view_video.php?viewkey=" + identifier;
25+
final String imageUrl = element.getElementsByTag("img").first().attr("src");
26+
27+
return new AudioTrackInfo(
28+
title, author, duration, identifier, false, uri, imageUrl, null
29+
);
30+
}
31+
}

source-managers/src/main/java/com/dunctebot/sourcemanagers/pornhub/PornHubAudioSourceManager.java

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,20 @@
2222
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
2323
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException.Severity;
2424
import com.sedmelluq.discord.lavaplayer.tools.JsonBrowser;
25-
import com.sedmelluq.discord.lavaplayer.track.AudioItem;
26-
import com.sedmelluq.discord.lavaplayer.track.AudioReference;
27-
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
28-
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
25+
import com.sedmelluq.discord.lavaplayer.track.*;
2926
import org.apache.commons.io.IOUtils;
3027
import org.apache.http.client.methods.CloseableHttpResponse;
3128
import org.apache.http.client.methods.HttpGet;
29+
import org.jsoup.Jsoup;
3230

3331
import java.io.DataInput;
3432
import java.io.DataOutput;
3533
import java.io.IOException;
34+
import java.net.URLEncoder;
3635
import java.nio.charset.StandardCharsets;
3736
import java.util.regex.Matcher;
3837
import java.util.regex.Pattern;
38+
import java.util.stream.Collectors;
3939

4040
public class PornHubAudioSourceManager extends AbstractDuncteBotHttpSource {
4141
private static final String DOMAIN_PATTERN = "https?://([a-z]+\\.)?pornhub\\.(com|net|org)";
@@ -44,18 +44,21 @@ public class PornHubAudioSourceManager extends AbstractDuncteBotHttpSource {
4444
public static final Pattern VIDEO_INFO_REGEX = Pattern.compile("var flashvars_\\d+ = (\\{.+})");
4545
private static final Pattern MODEL_INFO_REGEX = Pattern.compile("var MODEL_PROFILE = (\\{.+})");
4646

47+
private static final String SEARCH_PREFIX = "phsearch";
48+
private static final String SEARCH_PREFIX_DEFAULT = "phsearch:";
49+
4750
@Override
4851
public String getSourceName() {
4952
return "pornhub";
5053
}
5154

5255
@Override
5356
public AudioItem loadItem(AudioPlayerManager manager, AudioReference reference) {
54-
if (!VIDEO_REGEX.matcher(reference.identifier).matches()) {
55-
return null;
56-
}
57-
5857
try {
58+
if (!VIDEO_REGEX.matcher(reference.identifier).matches()) {
59+
return processAsSearchQuery(reference);
60+
}
61+
5962
return loadItemOnce(reference);
6063
} catch (Exception e) {
6164
throw ExceptionTools.wrapUnfriendlyExceptions("Something went wrong", Severity.SUSPICIOUS, e);
@@ -77,6 +80,56 @@ public AudioTrack decodeTrack(AudioTrackInfo trackInfo, DataInput input) {
7780
return new PornHubAudioTrack(trackInfo, this);
7881
}
7982

83+
private AudioItem processAsSearchQuery(AudioReference reference) throws IOException {
84+
if (reference.identifier.startsWith(SEARCH_PREFIX)) {
85+
if (reference.identifier.startsWith(SEARCH_PREFIX_DEFAULT)) {
86+
return attemptSearch(reference.identifier.substring(SEARCH_PREFIX_DEFAULT.length()).trim());
87+
}
88+
}
89+
90+
return null;
91+
}
92+
93+
public AudioItem attemptSearch(String query) throws IOException {
94+
// https://www.pornhub.com/video/search?search=a+few+words
95+
96+
final String html = loadHtml(
97+
"https://www.pornhub.com/video/search?search=" +
98+
URLEncoder.encode(query, StandardCharsets.UTF_8)
99+
);
100+
101+
if (html == null) {
102+
notAvailable();
103+
}
104+
105+
// ul#videoSearchResult -> contains results
106+
// li.pcVideoListItem -> contains all videos
107+
108+
final var document = Jsoup.parse(html);
109+
final var results = document.select("ul#videoSearchResult").first();
110+
111+
if (results == null) {
112+
throw new FriendlyException(
113+
"Search result element not found, contact dev",
114+
Severity.SUSPICIOUS,
115+
new IllegalArgumentException("Search result element not found, contact dev")
116+
);
117+
}
118+
119+
final var videos = results.select("li.pcVideoListItem");
120+
121+
final var phTracks = videos.stream()
122+
.map((it) -> PHHelpers.trackFromSearchElement(it, this))
123+
.collect(Collectors.toList());
124+
125+
return new BasicAudioPlaylist(
126+
"Search results for " + query,
127+
phTracks,
128+
null,
129+
true
130+
);
131+
}
132+
80133
private AudioItem loadItemOnce(AudioReference reference) throws IOException {
81134
final String html = loadHtml(reference.identifier);
82135

@@ -163,7 +216,7 @@ private JsonBrowser getModelInfo(String html) throws IOException {
163216
private String loadHtml(String url) throws IOException {
164217
final HttpGet httpGet = new HttpGet(url);
165218

166-
httpGet.setHeader("Cookie", "platform=pc; age_verified=1");
219+
httpGet.setHeader("Cookie", "platform=pc; age_verified=1; accessAgeDisclaimerPH=1");
167220

168221
try (final CloseableHttpResponse response = getHttpInterface().execute(httpGet)) {
169222
final int statusCode = response.getStatusLine().getStatusCode();

source-managers/src/main/java/com/dunctebot/sourcemanagers/pornhub/PornHubAudioTrack.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ private String parseJsValueToUrl(String htmlPage, String js) {
156156
private String loadMp4Url(String jsonPage, String cookie) throws IOException {
157157
final HttpGet mediaGet = new HttpGet(jsonPage);
158158

159-
mediaGet.setHeader("Cookie", cookie + "; platform=pc; age_verified=1");
159+
mediaGet.setHeader("Cookie", cookie + "; platform=pc; age_verified=1; accessAgeDisclaimerPH=1");
160160
mediaGet.setHeader("Referer", getPlayerPage(this.trackInfo.identifier));
161161

162162
try (final CloseableHttpResponse response = this.getSourceManager().getHttpInterface().execute(mediaGet)) {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2022 Duncan "duncte123" Sterken
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import com.dunctebot.sourcemanagers.pornhub.PornHubAudioSourceManager;
18+
import com.dunctebot.sourcemanagers.pornhub.PornHubAudioTrack;
19+
import com.sedmelluq.discord.lavaplayer.track.AudioReference;
20+
21+
public class PHSearchTest {
22+
public static void main(String[] args) throws Exception {
23+
// final var link = "https://www.pornhub.com/view_video.php?viewkey=ph5fc5ef73cfc87";
24+
final var link = "https://www.pornhub.com/view_video.php?viewkey=ph6383940fcb8d7";
25+
final var mngr = new PornHubAudioSourceManager();
26+
27+
final var test = mngr.attemptSearch("minecraft bedwards");
28+
29+
System.out.println(test);
30+
}
31+
}

0 commit comments

Comments
 (0)