Skip to content

Commit 0c632e1

Browse files
authored
Merge pull request #27 from TeamNewPipe/kiosk
add Kiosk support
2 parents 7ae274b + f64c82f commit 0c632e1

20 files changed

Lines changed: 879 additions & 19 deletions

src/main/java/org/schabi/newpipe/extractor/InfoItem.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package org.schabi.newpipe.extractor;
22

33
/*
4-
* Created by the-scrabi on 11.02.17.
4+
* Created by Christian Schabesberger on 11.02.17.
55
*
66
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
77
* InfoItem.java is part of NewPipe.

src/main/java/org/schabi/newpipe/extractor/StreamingService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
44
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
5+
import org.schabi.newpipe.extractor.kiosk.KioskList;
56
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
67
import org.schabi.newpipe.extractor.search.SearchEngine;
78
import org.schabi.newpipe.extractor.stream.StreamExtractor;
@@ -48,6 +49,7 @@ public ServiceInfo getServiceInfo() {
4849
public abstract StreamExtractor getStreamExtractor(String url) throws IOException, ExtractionException;
4950
public abstract ChannelExtractor getChannelExtractor(String url, String nextStreamsUrl) throws IOException, ExtractionException;
5051
public abstract PlaylistExtractor getPlaylistExtractor(String url, String nextStreamsUrl) throws IOException, ExtractionException;
52+
public abstract KioskList getKioskList() throws ExtractionException;
5153

5254
public ChannelExtractor getChannelExtractor(String url) throws IOException, ExtractionException {
5355
return getChannelExtractor(url, null);
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package org.schabi.newpipe.extractor.kiosk;
2+
3+
/*
4+
* Created by Christian Schabesberger on 12.08.17.
5+
*
6+
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
7+
* KioskExtractor.java is part of NewPipe.
8+
*
9+
* NewPipe is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* NewPipe is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
21+
*/
22+
23+
import org.schabi.newpipe.extractor.ListExtractor;
24+
import org.schabi.newpipe.extractor.StreamingService;
25+
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
26+
import org.schabi.newpipe.extractor.exceptions.ParsingException;
27+
28+
import java.io.IOException;
29+
30+
public abstract class KioskExtractor extends ListExtractor {
31+
private String contentCountry = null;
32+
33+
public KioskExtractor(StreamingService streamingService,
34+
String url,
35+
String nextStreamsUrl)
36+
throws IOException, ExtractionException {
37+
super(streamingService, url, nextStreamsUrl);
38+
this.contentCountry = contentCountry;
39+
}
40+
41+
/**
42+
* For certain Websites the content of a kiosk will be different depending
43+
* on the country you want to poen the website in. Therefore you should
44+
* set the contentCountry.
45+
* @param contentCountry Set the country decoded as Country Code: http://www.1728.org/countries.htm
46+
*/
47+
public void setContentCountry(String contentCountry) {
48+
this.contentCountry = contentCountry;
49+
}
50+
51+
/**
52+
* Returns the type of the kiosk.
53+
* eg. Trending, Top & Hot, Top last 24 hours
54+
* @return type of kiosk
55+
*/
56+
public abstract String getType() throws ParsingException;
57+
58+
@Override
59+
public String getId() throws ParsingException {
60+
return getType();
61+
}
62+
63+
@Override
64+
public String getName() throws ParsingException {
65+
return getType();
66+
}
67+
68+
public String getContentCountry() {
69+
return contentCountry;
70+
}
71+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package org.schabi.newpipe.extractor.kiosk;
2+
3+
/*
4+
* Created by Christian Schabesberger on 12.08.17.
5+
*
6+
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
7+
* KioskInfo.java is part of NewPipe.
8+
*
9+
* NewPipe is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* NewPipe is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
21+
*/
22+
23+
import org.schabi.newpipe.extractor.ListInfo;
24+
import org.schabi.newpipe.extractor.NewPipe;
25+
import org.schabi.newpipe.extractor.ServiceList;
26+
import org.schabi.newpipe.extractor.StreamingService;
27+
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
28+
import org.schabi.newpipe.extractor.exceptions.ParsingException;
29+
import org.schabi.newpipe.extractor.stream.StreamInfoItemCollector;
30+
31+
import java.io.IOException;
32+
33+
public class KioskInfo extends ListInfo {
34+
public String type;
35+
36+
public static KioskInfo getInfo(String url,
37+
String contentCountry) throws IOException, ExtractionException {
38+
return getInfo(NewPipe.getServiceByUrl(url), url, contentCountry);
39+
}
40+
41+
public static KioskInfo getInfo(ServiceList serviceItem,
42+
String url,
43+
String contentContry) throws IOException, ExtractionException {
44+
return getInfo(serviceItem.getService(), url, contentContry);
45+
}
46+
47+
public static KioskInfo getInfo(StreamingService service,
48+
String url,
49+
String contentCountry) throws IOException, ExtractionException {
50+
KioskList kl = service.getKioskList();
51+
KioskExtractor extractor = kl.getExtryctorByUrl(url);
52+
return getInfo(extractor, contentCountry);
53+
}
54+
55+
public static KioskInfo getInfo(KioskExtractor extractor,
56+
String contentCountry) throws IOException, ExtractionException {
57+
KioskInfo info = new KioskInfo();
58+
extractor.setContentCountry(contentCountry);
59+
extractor.fetchPage();
60+
info.type = extractor.getType();
61+
info.name = extractor.getName();
62+
info.id = extractor.getId();
63+
64+
try {
65+
StreamInfoItemCollector c = extractor.getStreams();
66+
info.related_streams = c.getItemList();
67+
info.errors.addAll(c.getErrors());
68+
} catch (Exception e) {
69+
info.errors.add(e);
70+
}
71+
72+
return info;
73+
}
74+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.schabi.newpipe.extractor.kiosk;
2+
3+
import org.schabi.newpipe.extractor.UrlIdHandler;
4+
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
5+
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
import java.util.Set;
9+
10+
public class KioskList {
11+
private int service_id;
12+
private HashMap<String, KioskEntry> kioskList = new HashMap<>();
13+
14+
private class KioskEntry {
15+
public KioskEntry(KioskExtractor e, UrlIdHandler h) {
16+
extractor = e;
17+
handler = h;
18+
}
19+
KioskExtractor extractor;
20+
UrlIdHandler handler;
21+
}
22+
23+
public KioskList(int service_id) {
24+
this.service_id = service_id;
25+
}
26+
27+
public void addKioskEntry(KioskExtractor extractor, UrlIdHandler handler)
28+
throws Exception {
29+
if(kioskList.get(extractor.getType()) != null) {
30+
throw new Exception("Kiosk with type " + extractor.getType() + " already exists.");
31+
}
32+
kioskList.put(extractor.getType(), new KioskEntry(extractor, handler));
33+
}
34+
35+
public KioskExtractor getExtractorByType(String kioskType) throws ExtractionException {
36+
KioskEntry ke = kioskList.get(kioskType);
37+
if(ke == null) {
38+
throw new ExtractionException("No kiosk found with the type: " + kioskType);
39+
} else {
40+
return ke.extractor;
41+
}
42+
}
43+
44+
public Set<String> getAvailableKisokTypes() {
45+
return kioskList.keySet();
46+
}
47+
48+
public KioskExtractor getExtryctorByUrl(String url) throws ExtractionException {
49+
for(Map.Entry<String, KioskEntry> e : kioskList.entrySet()) {
50+
KioskEntry ke = e.getValue();
51+
if(ke.handler.acceptUrl(url)) {
52+
return getExtractorByType(e.getKey());
53+
}
54+
}
55+
throw new ExtractionException("Could not find a kiosk that fits to the url: " + url);
56+
}
57+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package org.schabi.newpipe.extractor.services.soundcloud;
2+
3+
import java.io.IOException;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
7+
import org.schabi.newpipe.extractor.StreamingService;
8+
import org.schabi.newpipe.extractor.UrlIdHandler;
9+
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
10+
import org.schabi.newpipe.extractor.exceptions.ParsingException;
11+
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
12+
import org.schabi.newpipe.extractor.stream.StreamInfoItemCollector;
13+
14+
public class SoundcloudChartsExtractor extends KioskExtractor {
15+
private String url;
16+
17+
public SoundcloudChartsExtractor(StreamingService service, String url, String nextStreamsUrl) throws IOException, ExtractionException {
18+
super(service, url, nextStreamsUrl);
19+
this.url = url;
20+
}
21+
22+
@Override
23+
public void fetchPage() {
24+
}
25+
26+
@Override
27+
public String getType() throws ParsingException {
28+
return getUrlIdHandler().getId(url);
29+
}
30+
31+
@Override
32+
public UrlIdHandler getUrlIdHandler() {
33+
return new SoundcloudChartsUrlIdHandler();
34+
}
35+
36+
@Override
37+
public NextItemsResult getNextStreams() throws IOException, ExtractionException {
38+
if (!hasMoreStreams()) {
39+
throw new ExtractionException("Chart doesn't have more streams");
40+
}
41+
42+
StreamInfoItemCollector collector = new StreamInfoItemCollector(getServiceId());
43+
nextStreamsUrl = SoundcloudParsingHelper.getStreamsFromApi(collector, nextStreamsUrl, true);
44+
45+
return new NextItemsResult(collector, nextStreamsUrl);
46+
}
47+
48+
@Override
49+
public StreamInfoItemCollector getStreams() throws IOException, ExtractionException {
50+
StreamInfoItemCollector collector = new StreamInfoItemCollector(getServiceId());
51+
52+
String apiUrl = "https://api-v2.soundcloud.com/charts" +
53+
"?genre=soundcloud:genres:all-music" +
54+
"&client_id=" + SoundcloudParsingHelper.clientId();
55+
56+
if (getType().equals("Top 50")) {
57+
apiUrl += "&kind=top";
58+
} else {
59+
apiUrl += "&kind=new";
60+
}
61+
62+
List<String> supportedCountries = Arrays.asList("AU", "CA", "FR", "DE", "IE", "NL", "NZ", "GB", "US");
63+
String contentCountry = getContentCountry();
64+
if (supportedCountries.contains(contentCountry)) {
65+
apiUrl += "&region=soundcloud:regions:" + contentCountry;
66+
}
67+
68+
nextStreamsUrl = SoundcloudParsingHelper.getStreamsFromApi(collector, apiUrl, true);
69+
return collector;
70+
}
71+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.schabi.newpipe.extractor.services.soundcloud;
2+
3+
import org.schabi.newpipe.extractor.UrlIdHandler;
4+
import org.schabi.newpipe.extractor.utils.Parser;
5+
6+
public class SoundcloudChartsUrlIdHandler implements UrlIdHandler {
7+
public String getUrl(String id) {
8+
if (id.equals("Top 50")) {
9+
return "https://soundcloud.com/charts/top";
10+
} else {
11+
return "https://soundcloud.com/charts/new";
12+
}
13+
}
14+
15+
@Override
16+
public String getId(String url) {
17+
if (Parser.isMatch("^https?://(www\\.)?soundcloud.com/charts(/top)?/?([#?].*)?$", url.toLowerCase())) {
18+
return "Top 50";
19+
} else {
20+
return "New & hot";
21+
}
22+
}
23+
24+
@Override
25+
public String cleanUrl(String url) {
26+
if (Parser.isMatch("^https?://(www\\.)?soundcloud.com/charts(/top)?/?([#?].*)?$", url.toLowerCase())) {
27+
return "https://soundcloud.com/charts/top";
28+
} else {
29+
return "https://soundcloud.com/charts/new";
30+
}
31+
}
32+
33+
@Override
34+
public boolean acceptUrl(String url) {
35+
return Parser.isMatch("^https?://(www\\.)?soundcloud.com/charts(/top|/new)?/?([#?].*)?$", url.toLowerCase());
36+
}
37+
}

src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public static String getStreamsFromApiMinItems(int minItems, StreamInfoItemColle
127127
*
128128
* @return the next streams url, empty if don't have
129129
*/
130-
public static String getStreamsFromApi(StreamInfoItemCollector collector, String apiUrl) throws IOException, ReCaptchaException, ParsingException {
130+
public static String getStreamsFromApi(StreamInfoItemCollector collector, String apiUrl, boolean charts) throws IOException, ReCaptchaException, ParsingException {
131131
String response = NewPipe.getDownloader().download(apiUrl);
132132
JsonObject responseObject;
133133
try {
@@ -151,4 +151,8 @@ public static String getStreamsFromApi(StreamInfoItemCollector collector, String
151151

152152
return nextStreamsUrl;
153153
}
154+
155+
public static String getStreamsFromApi(StreamInfoItemCollector collector, String apiUrl) throws ReCaptchaException, ParsingException, IOException {
156+
return getStreamsFromApi(collector, apiUrl, false);
157+
}
154158
}

src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudService.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
package org.schabi.newpipe.extractor.services.soundcloud;
22

3+
import java.io.IOException;
4+
35
import org.schabi.newpipe.extractor.StreamingService;
46
import org.schabi.newpipe.extractor.SuggestionExtractor;
57
import org.schabi.newpipe.extractor.UrlIdHandler;
68
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
79
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
10+
import org.schabi.newpipe.extractor.kiosk.KioskList;
811
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
912
import org.schabi.newpipe.extractor.search.SearchEngine;
1013
import org.schabi.newpipe.extractor.stream.StreamExtractor;
1114

12-
import java.io.IOException;
13-
1415
public class SoundcloudService extends StreamingService {
1516

1617
public SoundcloudService(int id, String name) {
@@ -57,4 +58,20 @@ public PlaylistExtractor getPlaylistExtractor(String url, String nextStreamsUrl)
5758
public SuggestionExtractor getSuggestionExtractor() {
5859
return new SoundcloudSuggestionExtractor(getServiceId());
5960
}
61+
62+
@Override
63+
public KioskList getKioskList() throws ExtractionException {
64+
KioskList list = new KioskList(getServiceId());
65+
66+
// add kiosks here e.g.:
67+
SoundcloudChartsUrlIdHandler h = new SoundcloudChartsUrlIdHandler();
68+
try {
69+
list.addKioskEntry(new SoundcloudChartsExtractor(this, h.getUrl("Top 50"), null), h);
70+
list.addKioskEntry(new SoundcloudChartsExtractor(this, h.getUrl("New & hot"), null), h);
71+
} catch (Exception e) {
72+
throw new ExtractionException(e);
73+
}
74+
75+
return list;
76+
}
6077
}

0 commit comments

Comments
 (0)