-
-
Notifications
You must be signed in to change notification settings - Fork 494
Bandcamp support #232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Bandcamp support #232
Changes from 86 commits
Commits
Show all changes
104 commits
Select commit
Hold shift + click to select a range
a579337
Bandcamp service with support for streams and searches
fynngodau 43dc3c3
Return empty kiosk list instead of null
fynngodau 80d67e2
Return mp3-128 audio stream [experimental]
fynngodau c3d127c
Bandcamp audio stream test and fix
fynngodau 5281456
Bandcamp channel link handler factory
fynngodau a42c774
Bandcamp channel extractor (ignoring everything but tracks)
fynngodau 7730eb2
Bandcamp channel extractor: enforce https when getting banner url
fynngodau d5cdc20
Bandcmap channel extractor: fix getting banner url
fynngodau 91c0ec7
Bandcamp stream extractor: catch NullPointerException
fynngodau 794ca5e
Bandcamp channel extractor: handel nonexistent images better
fynngodau d05b14a
Add channels (artists) to search results
fynngodau ba700bf
Add bandcamp playlists (albums)
fynngodau 655df35
Various improvements concerning bandcamp playlists
fynngodau e12ddae
Bandcamp playlist and search extractors: better and more tests
fynngodau ce2a88e
Add bandcamp search suggestion extractor
fynngodau 9b16baf
Bandcamp search: multiple pages
fynngodau 13e4908
Bandcamp search extractor: read track count from result page
fynngodau db02850
Bandcamp playlist extractor: support playlists with just one stream
fynngodau 13ef11e
Bandcamp featured kiosk
fynngodau 808c8aa
Add bandcamp weekly kiosk
fynngodau f0d36df
Bandcamp radio: proper name, date shortened
fynngodau 46e1f39
Refuse to load bandcamp playlists without content
fynngodau ba967f1
Workaround enourmous load times for long bandcamp playlists
fynngodau 7b5702b
Add bandcamp to list of supported services in README
fynngodau 623e6a8
Merge branch 'dev' into dev
fynngodau 36a316e
Merge branch 'dev' into dev
fynngodau b78f788
Merge branch 'dev' into dev
fynngodau a1523eb
Update Bandcamp service to latest interface changes
fynngodau 5c0a033
Merge 'origin/dev' into dev
fynngodau 9c23937
Change nanojson dependency to @wb9688's fork
fynngodau b100b98
Bandcmap: Use nanojson fork instead of org.json
fynngodau c133190
Bandcamp capitalization
fynngodau 67de028
Bandcamp: Generate query JSON in a proper way
fynngodau 433d72c
Depend on nanojson fork in timeago-parser
fynngodau 00c0333
Bandcamp: Fetch channelInfo in onFetchPage
fynngodau 8209959
Bandcamp: Move code from SearchExtractor to InfoItemExtractors
fynngodau 965bce0
Bandcamp stream extractor: return NO_AGE_LIMIT
fynngodau 9201e0d
Don't declare exceptions that can't actually be thrown
fynngodau 10ae3db
Bandcamp javadoc: Replace br tags with p tags
fynngodau 8c70dab
Bandcamp search query handler factory: inline variable
fynngodau b5e251c
Bandcamp channel extractor: package-private access for getImageUrl(…)
fynngodau 5009d9f
Bandcamp tests: remove certain tests
fynngodau f71bd29
Bandcamp playlist extractor: add more tests
fynngodau 9bc7a47
Replace fori with foreach loop
fynngodau a3e8e1c
Bandcamp: move own methods to helper class
fynngodau e7b046d
Merge remote-tracking branch 'origin/dev' into dev
fynngodau fff21ca
Fix Bandcamp no avatar test
fynngodau 692b2d0
Bandcamp: read info item data in place and not in advance
fynngodau e08256e
Remove "url cleanup" in Bandcamp link handlers
fynngodau 89b0639
New Bandcamp tests for channel extractor
fynngodau dd955c7
Merge branch 'origin/dev' into dev
fynngodau 9fa9d92
Bandcamp: Implement new methods required due to interface changes
fynngodau 3940138
Fix Bandcamp capitalization in one more spot
fynngodau de77656
Bandcamp: fix loading uploader from streams in search
fynngodau 8f6c00f
Use default test in BandcampSearchExtractorTest
fynngodau e98bff8
Improved Bandcamp radio stream extractor tests
fynngodau 6822fe3
Bandcamp: Get Stream upload date
fynngodau 1be20ce
Bandcamp: parse date
fynngodau 34b6928
Don't print stacktrace before throwing new exception
fynngodau ea49202
Don't display internal license id
fynngodau 27e7aad
Bandcamp: Improve code style
fynngodau e6ecd91
Bandcamp: Test full date
fynngodau 0950a95
Fix for testing wrong object for null or empty
fynngodau 8fa8153
Better bandcamp stream extractor description test
fynngodau 52103ac
Remove "useless" comments
fynngodau 4dd9540
Bandcamp license switch order
fynngodau e13f341
Bandcamp stream extractor: test service id
fynngodau 9a555d9
Remove useless bandcamp tests
fynngodau 39b55b5
Bandcamp radio stream extractor: test uploader url
fynngodau 96de834
Bandcamp: parse date from radio info item
fynngodau c12ef3a
Merge TNP/dev into fynngodau/dev
fynngodau 932d094
Upgrade featured playlist urls to https
fynngodau cfe88a7
Throw ContentNotSupportedException when opening radio uploader channel
fynngodau 81b5e7c
Fix extractor
fynngodau 6bc7e34
Merge TNP/dev into fynngodau/dev
fynngodau 186936d
Various changes regarding tests
fynngodau 8c369b0
Rephrase link in javadoc
fynngodau 99e7ef0
[Bandcamp] Apply small changes to code formatting and style
TobiGr c91e21b
[Bandcamp] Tests - Add finals and improve code formatting
TobiGr be562b8
Change tests
fynngodau 04dd3d4
Rework link handlers to correctly accept external websites
fynngodau df16a86
[Bandcamp] Improve radio stream extractor test
TobiGr 116e921
Merge remote-tracking branch 'origin/dev' into bandcamp
TobiGr 74b46fe
[Bandcamp] Fix deprecation in parseDate helper function
TobiGr 5090373
[Bandcamp] Fix accepting HTTP URLs
TobiGr c9e9953
[Bandcamp] Fix channel link handler factory
fynngodau 78c2113
Merge remote-tracking branch 'origin/dev' into bandcamp
TobiGr 0757055
Fix build and optimize imports
TobiGr e062c8c
Merge branch 'dev' into bandcamp
TobiGr 5bf9fdd
Code improvements
TobiGr 1697312
Use Collections.emptyList() instead of Collections.EMPTY_LIST or new …
TobiGr 54b8e54
Fix potential NPE
TobiGr 54aa5b3
Use propper structure in KioskExtractors
TobiGr 98268e3
Move radio URL check into a function
TobiGr fa61b86
Code improvements
TobiGr 91e9309
Merge remote-tracking branch 'origin/dev' into bandcamp
TobiGr 02920fa
Add isUploaderVerified()
TobiGr ea120a4
remove print stacktrace
TobiGr adde433
Code improvements
TobiGr c07db80
Add BASE_URL and BASE_API_URL to BandcampExtractorHelper
TobiGr b9e8ee8
Rename BandcampExtractorHelper.smartConcatenate(String[], String) to …
TobiGr 70814dc
Fix Utils.nonEmptyAndNullJoin
TobiGr a1688fe
Move BandcampExtractorHelper.getJsonData(String, String) to JsonUtils
TobiGr 22fa131
Merge branch 'dev' into bandcamp
TobiGr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
126 changes: 126 additions & 0 deletions
126
extractor/src/main/java/org/schabi/newpipe/extractor/services/bandcamp/BandcampService.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| // Created by Fynn Godau 2019, licensed GNU GPL version 3 or later | ||
|
|
||
| package org.schabi.newpipe.extractor.services.bandcamp; | ||
|
|
||
| import org.schabi.newpipe.extractor.StreamingService; | ||
| import org.schabi.newpipe.extractor.channel.ChannelExtractor; | ||
| import org.schabi.newpipe.extractor.comments.CommentsExtractor; | ||
| import org.schabi.newpipe.extractor.exceptions.ExtractionException; | ||
| import org.schabi.newpipe.extractor.kiosk.KioskList; | ||
| import org.schabi.newpipe.extractor.linkhandler.*; | ||
| import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; | ||
| import org.schabi.newpipe.extractor.search.SearchExtractor; | ||
| import org.schabi.newpipe.extractor.services.bandcamp.extractors.*; | ||
| import org.schabi.newpipe.extractor.services.bandcamp.linkHandler.*; | ||
| import org.schabi.newpipe.extractor.stream.StreamExtractor; | ||
| import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; | ||
| import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor; | ||
|
|
||
| import java.util.Collections; | ||
|
|
||
| import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO; | ||
| import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampFeaturedExtractor.FEATURED_API_URL; | ||
| import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampFeaturedExtractor.KIOSK_FEATURED; | ||
| import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampRadioExtractor.KIOSK_RADIO; | ||
| import static org.schabi.newpipe.extractor.services.bandcamp.extractors.BandcampRadioExtractor.RADIO_API_URL; | ||
|
|
||
| public class BandcampService extends StreamingService { | ||
B0pol marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| public BandcampService(final int id) { | ||
| super(id, "Bandcamp", Collections.singletonList(AUDIO)); | ||
| } | ||
|
|
||
| @Override | ||
| public String getBaseUrl() { | ||
| return "https://bandcamp.com"; | ||
| } | ||
|
|
||
| @Override | ||
| public LinkHandlerFactory getStreamLHFactory() { | ||
| return new BandcampStreamLinkHandlerFactory(); | ||
| } | ||
|
|
||
| @Override | ||
| public ListLinkHandlerFactory getChannelLHFactory() { | ||
| return new BandcampChannelLinkHandlerFactory(); | ||
| } | ||
|
|
||
| @Override | ||
| public ListLinkHandlerFactory getPlaylistLHFactory() { | ||
| return new BandcampPlaylistLinkHandlerFactory(); | ||
| } | ||
|
|
||
| @Override | ||
| public SearchQueryHandlerFactory getSearchQHFactory() { | ||
| return new BandcampSearchQueryHandlerFactory(); | ||
| } | ||
|
|
||
| @Override | ||
| public ListLinkHandlerFactory getCommentsLHFactory() { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public SearchExtractor getSearchExtractor(final SearchQueryHandler queryHandler) { | ||
| return new BandcampSearchExtractor(this, queryHandler); | ||
| } | ||
|
|
||
| @Override | ||
| public SuggestionExtractor getSuggestionExtractor() { | ||
| return new BandcampSuggestionExtractor(this); | ||
| } | ||
|
|
||
| @Override | ||
| public SubscriptionExtractor getSubscriptionExtractor() { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public KioskList getKioskList() throws ExtractionException { | ||
|
|
||
| KioskList kioskList = new KioskList(this); | ||
|
|
||
| try { | ||
| kioskList.addKioskEntry((streamingService, url, kioskId) -> | ||
| new BandcampFeaturedExtractor( | ||
| BandcampService.this, | ||
| new BandcampFeaturedLinkHandlerFactory().fromUrl(FEATURED_API_URL), kioskId), | ||
| new BandcampFeaturedLinkHandlerFactory(), KIOSK_FEATURED); | ||
|
|
||
| kioskList.addKioskEntry((streamingService, url, kioskId) -> | ||
| new BandcampRadioExtractor(BandcampService.this, | ||
| new BandcampFeaturedLinkHandlerFactory().fromUrl(RADIO_API_URL), kioskId), | ||
| new BandcampFeaturedLinkHandlerFactory(), KIOSK_RADIO); | ||
|
|
||
| kioskList.setDefaultKiosk(KIOSK_FEATURED); | ||
|
|
||
| } catch (final Exception e) { | ||
| throw new ExtractionException(e); | ||
| } | ||
|
|
||
| return kioskList; | ||
| } | ||
|
|
||
| @Override | ||
| public ChannelExtractor getChannelExtractor(final ListLinkHandler linkHandler) { | ||
| return new BandcampChannelExtractor(this, linkHandler); | ||
| } | ||
|
|
||
| @Override | ||
| public PlaylistExtractor getPlaylistExtractor(final ListLinkHandler linkHandler) { | ||
| return new BandcampPlaylistExtractor(this, linkHandler); | ||
| } | ||
|
|
||
| @Override | ||
| public StreamExtractor getStreamExtractor(final LinkHandler linkHandler) { | ||
| if (linkHandler.getUrl().matches("https?://bandcamp\\.com/\\?show=\\d+")) | ||
| return new BandcampRadioStreamExtractor(this, linkHandler); | ||
| else | ||
| return new BandcampStreamExtractor(this, linkHandler); | ||
| } | ||
|
|
||
| @Override | ||
| public CommentsExtractor getCommentsExtractor(ListLinkHandler linkHandler) { | ||
| return null; | ||
| } | ||
| } | ||
132 changes: 132 additions & 0 deletions
132
...a/org/schabi/newpipe/extractor/services/bandcamp/extractors/BandcampChannelExtractor.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| // Created by Fynn Godau 2019, licensed GNU GPL version 3 or later | ||
|
|
||
| package org.schabi.newpipe.extractor.services.bandcamp.extractors; | ||
|
|
||
| import com.grack.nanojson.JsonArray; | ||
| import com.grack.nanojson.JsonObject; | ||
| import org.jsoup.Jsoup; | ||
| import org.schabi.newpipe.extractor.Page; | ||
| import org.schabi.newpipe.extractor.StreamingService; | ||
| import org.schabi.newpipe.extractor.channel.ChannelExtractor; | ||
| import org.schabi.newpipe.extractor.downloader.Downloader; | ||
| import org.schabi.newpipe.extractor.exceptions.ExtractionException; | ||
| import org.schabi.newpipe.extractor.exceptions.ParsingException; | ||
| import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; | ||
| import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; | ||
| import org.schabi.newpipe.extractor.services.bandcamp.extractors.streaminfoitem.BandcampDiscographStreamInfoItemExtractor; | ||
| import org.schabi.newpipe.extractor.stream.StreamInfoItem; | ||
| import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector; | ||
|
|
||
| import javax.annotation.Nonnull; | ||
| import java.io.IOException; | ||
|
|
||
| public class BandcampChannelExtractor extends ChannelExtractor { | ||
|
|
||
| private JsonObject channelInfo; | ||
|
|
||
| public BandcampChannelExtractor(final StreamingService service, final ListLinkHandler linkHandler) { | ||
| super(service, linkHandler); | ||
| } | ||
|
|
||
| @Override | ||
| public String getAvatarUrl() { | ||
| if (channelInfo.getLong("bio_image_id") == 0) return ""; | ||
|
|
||
| return BandcampExtractorHelper.getImageUrl(channelInfo.getLong("bio_image_id"), false); | ||
| } | ||
|
|
||
| @Override | ||
| public String getBannerUrl() throws ParsingException { | ||
| /* | ||
| * Why does the mobile endpoint not contain the header?? Or at least not the same one? | ||
| * Anyway we're back to querying websites | ||
| */ | ||
| try { | ||
| final String html = getDownloader() | ||
| .get(channelInfo.getString("bandcamp_url").replace("http://", "https://")) | ||
| .responseBody(); | ||
|
|
||
| return Jsoup.parse(html) | ||
| .getElementById("customHeader") | ||
| .getElementsByTag("img") | ||
| .first() | ||
| .attr("src"); | ||
|
|
||
| } catch (final IOException | ReCaptchaException e) { | ||
| throw new ParsingException("Could not download artist web site", e); | ||
| } catch (final NullPointerException e) { | ||
| // No banner available | ||
| return ""; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * bandcamp stopped providing RSS feeds when appending /feed to any URL | ||
| * because too few people used it. | ||
| */ | ||
| @Override | ||
| public String getFeedUrl() { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public long getSubscriberCount() { | ||
| return -1; | ||
| } | ||
|
|
||
| @Override | ||
| public String getDescription() { | ||
| return channelInfo.getString("bio"); | ||
| } | ||
|
|
||
| @Override | ||
| public String getParentChannelName() { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public String getParentChannelUrl() { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public String getParentChannelAvatarUrl() { | ||
| return null; | ||
| } | ||
|
|
||
| @Nonnull | ||
| @Override | ||
| public InfoItemsPage<StreamInfoItem> getInitialPage() throws ParsingException { | ||
|
|
||
| final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId()); | ||
|
|
||
| final JsonArray discography = channelInfo.getArray("discography"); | ||
|
|
||
| for (int i = 0; i < discography.size(); i++) { | ||
| // I define discograph as an item that can appear in a discography | ||
| final JsonObject discograph = discography.getObject(i); | ||
|
|
||
| if (!discograph.getString("item_type").equals("track")) continue; | ||
|
|
||
| collector.commit(new BandcampDiscographStreamInfoItemExtractor(discograph, getUrl())); | ||
| } | ||
|
|
||
| return new InfoItemsPage<>(collector, null); | ||
| } | ||
|
|
||
| @Override | ||
| public InfoItemsPage<StreamInfoItem> getPage(Page page) { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException { | ||
| channelInfo = BandcampExtractorHelper.getArtistDetails(getId()); | ||
| } | ||
|
|
||
| @Nonnull | ||
| @Override | ||
| public String getName() { | ||
| return channelInfo.getString("name"); | ||
| } | ||
| } |
53 changes: 53 additions & 0 deletions
53
...habi/newpipe/extractor/services/bandcamp/extractors/BandcampChannelInfoItemExtractor.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| // Created by Fynn Godau 2019, licensed GNU GPL version 3 or later | ||
|
|
||
| package org.schabi.newpipe.extractor.services.bandcamp.extractors; | ||
|
|
||
| import org.jsoup.nodes.Element; | ||
| import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor; | ||
| import org.schabi.newpipe.extractor.exceptions.ParsingException; | ||
|
|
||
| public class BandcampChannelInfoItemExtractor implements ChannelInfoItemExtractor { | ||
|
|
||
| private final Element resultInfo, searchResult; | ||
|
|
||
| public BandcampChannelInfoItemExtractor(final Element searchResult) { | ||
| this.searchResult = searchResult; | ||
| resultInfo = searchResult.getElementsByClass("result-info").first(); | ||
| } | ||
|
|
||
| @Override | ||
| public String getName() throws ParsingException { | ||
| return resultInfo.getElementsByClass("heading").text(); | ||
| } | ||
|
|
||
| @Override | ||
| public String getUrl() throws ParsingException { | ||
| return resultInfo.getElementsByClass("itemurl").text(); | ||
| } | ||
|
|
||
| @Override | ||
| public String getThumbnailUrl() throws ParsingException { | ||
| final Element img = searchResult.getElementsByClass("art").first() | ||
| .getElementsByTag("img").first(); | ||
| if (img != null) { | ||
| return img.attr("src"); | ||
| } else { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public String getDescription() { | ||
| return resultInfo.getElementsByClass("subhead").text(); | ||
| } | ||
|
|
||
| @Override | ||
| public long getSubscriberCount() { | ||
| return -1; | ||
| } | ||
|
|
||
| @Override | ||
| public long getStreamCount() { | ||
| return -1; | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.