22
22
import com .sedmelluq .discord .lavaplayer .tools .FriendlyException ;
23
23
import com .sedmelluq .discord .lavaplayer .tools .FriendlyException .Severity ;
24
24
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 .*;
29
26
import org .apache .commons .io .IOUtils ;
30
27
import org .apache .http .client .methods .CloseableHttpResponse ;
31
28
import org .apache .http .client .methods .HttpGet ;
29
+ import org .jsoup .Jsoup ;
32
30
33
31
import java .io .DataInput ;
34
32
import java .io .DataOutput ;
35
33
import java .io .IOException ;
34
+ import java .net .URLEncoder ;
36
35
import java .nio .charset .StandardCharsets ;
37
36
import java .util .regex .Matcher ;
38
37
import java .util .regex .Pattern ;
38
+ import java .util .stream .Collectors ;
39
39
40
40
public class PornHubAudioSourceManager extends AbstractDuncteBotHttpSource {
41
41
private static final String DOMAIN_PATTERN = "https?://([a-z]+\\ .)?pornhub\\ .(com|net|org)" ;
@@ -44,18 +44,21 @@ public class PornHubAudioSourceManager extends AbstractDuncteBotHttpSource {
44
44
public static final Pattern VIDEO_INFO_REGEX = Pattern .compile ("var flashvars_\\ d+ = (\\ {.+})" );
45
45
private static final Pattern MODEL_INFO_REGEX = Pattern .compile ("var MODEL_PROFILE = (\\ {.+})" );
46
46
47
+ private static final String SEARCH_PREFIX = "phsearch" ;
48
+ private static final String SEARCH_PREFIX_DEFAULT = "phsearch:" ;
49
+
47
50
@ Override
48
51
public String getSourceName () {
49
52
return "pornhub" ;
50
53
}
51
54
52
55
@ Override
53
56
public AudioItem loadItem (AudioPlayerManager manager , AudioReference reference ) {
54
- if (!VIDEO_REGEX .matcher (reference .identifier ).matches ()) {
55
- return null ;
56
- }
57
-
58
57
try {
58
+ if (!VIDEO_REGEX .matcher (reference .identifier ).matches ()) {
59
+ return processAsSearchQuery (reference );
60
+ }
61
+
59
62
return loadItemOnce (reference );
60
63
} catch (Exception e ) {
61
64
throw ExceptionTools .wrapUnfriendlyExceptions ("Something went wrong" , Severity .SUSPICIOUS , e );
@@ -77,6 +80,56 @@ public AudioTrack decodeTrack(AudioTrackInfo trackInfo, DataInput input) {
77
80
return new PornHubAudioTrack (trackInfo , this );
78
81
}
79
82
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
+
80
133
private AudioItem loadItemOnce (AudioReference reference ) throws IOException {
81
134
final String html = loadHtml (reference .identifier );
82
135
@@ -163,7 +216,7 @@ private JsonBrowser getModelInfo(String html) throws IOException {
163
216
private String loadHtml (String url ) throws IOException {
164
217
final HttpGet httpGet = new HttpGet (url );
165
218
166
- httpGet .setHeader ("Cookie" , "platform=pc; age_verified=1" );
219
+ httpGet .setHeader ("Cookie" , "platform=pc; age_verified=1; accessAgeDisclaimerPH=1 " );
167
220
168
221
try (final CloseableHttpResponse response = getHttpInterface ().execute (httpGet )) {
169
222
final int statusCode = response .getStatusLine ().getStatusCode ();
0 commit comments