Add getPodcasts call.

Signed-off-by: Yahor Berdnikau <egorr.berd@gmail.com>
This commit is contained in:
Yahor Berdnikau 2017-09-03 16:10:48 +02:00
parent 4b1d6e9827
commit 636968f03c
6 changed files with 280 additions and 1 deletions

View File

@ -0,0 +1,82 @@
package org.moire.ultrasonic.api.subsonic
import org.amshove.kluent.`should equal to`
import org.amshove.kluent.`should equal`
import org.amshove.kluent.`should not be`
import org.junit.Test
import org.moire.ultrasonic.api.subsonic.models.MusicDirectoryChild
/**
* Integration test for [SubsonicAPIClient] for getPodcasts call.
*/
class SubsonicApiGetPodcastsTest : SubsonicAPIClientTest() {
@Test
fun `Should handle error response`() {
val response = checkErrorCallParsed(mockWebServerRule) {
client.api.getPodcasts().execute()
}
response.podcastChannels `should not be` null
response.podcastChannels `should equal` emptyList()
}
@Test
fun `Should handle ok response`() {
mockWebServerRule.enqueueResponse("get_podcasts_ok.json")
val response = client.api.getPodcasts().execute()
assertResponseSuccessful(response)
val podcastChannelsList = response.body().podcastChannels
podcastChannelsList.size `should equal to` 1
with(podcastChannelsList[0]) {
id `should equal to` 2
url `should equal to` "http://feeds.codenewbie.org/cnpodcast.xml"
title `should equal to` "CodeNewbie"
description `should equal to` "Stories and interviews from people on their coding journey."
coverArt `should equal to` "pod-2"
originalImageUrl `should equal to` "http://codenewbie.blubrry.com/wp-content/uploads/powerpress/220808.jpg"
status `should equal to` "completed"
errorMessage `should equal to` ""
episodeList.size `should equal to` 10
episodeList[0] `should equal` MusicDirectoryChild(id = 148, parent = 9959, isDir = false,
title = "S1:EP3 How to teach yourself computer science (Vaidehi Joshi)",
album = "CodeNewbie", artist = "podcasts", coverArt = "9959",
size = 38274221, contentType = "audio/mpeg", suffix = "mp3",
duration = 2397, bitRate = 128, isVideo = false, playCount = 0,
created = parseDate("2017-08-30T09:33:39.000Z"), type = "podcast",
streamId = 9982, channelId = 2,
description = "Vaidehi decided to take on a year-long challenge. " +
"She'd pick a computer science topic every week, do tons of research " +
"and write a technical blog post explaining it in simple terms and " +
"beautiful illustrations. And then she actually did it. She tells us " +
"about her project, basecs, how it's changed her as a developer, and " +
"how she handles the trolls and negativity from people who don't " +
"appreciate her work. Show Notes Technical Writer position at " +
"CodeNewbie basecs 100 Days of Code Conway's Game of Life Hexes and " +
"Other Magical Numbers (Vaidehi's blog post) Bits, Bytes, Building " +
"With Binary (Vaidehi's blog post) Rust",
status = "completed", publishDate = parseDate("2017-08-29T00:01:01.000Z"))
}
}
@Test
fun `Should pass include episodes in request`() {
val includeEpisodes = true
mockWebServerRule.assertRequestParam(responseResourceName = "get_podcasts_ok.json",
expectedParam = "includeEpisodes=$includeEpisodes") {
client.api.getPodcasts(includeEpisodes = includeEpisodes).execute()
}
}
@Test
fun `Should pass id in request param`() {
val id = 249L
mockWebServerRule.assertRequestParam(responseResourceName = "get_podcasts_ok.json",
expectedParam = "id=$id") {
client.api.getPodcasts(id = id).execute()
}
}
}

View File

@ -0,0 +1,154 @@
{
"subsonic-response" : {
"status" : "ok",
"version" : "1.15.0",
"podcasts" : {
"channel" : [ {
"id" : "2",
"url" : "http://feeds.codenewbie.org/cnpodcast.xml",
"title" : "CodeNewbie",
"description" : "Stories and interviews from people on their coding journey.",
"coverArt" : "pod-2",
"originalImageUrl" : "http://codenewbie.blubrry.com/wp-content/uploads/powerpress/220808.jpg",
"status" : "completed",
"episode" : [ {
"id" : "148",
"parent" : "9959",
"isDir" : false,
"title" : "S1:EP3 How to teach yourself computer science (Vaidehi Joshi)",
"album" : "CodeNewbie",
"artist" : "podcasts",
"coverArt" : "9959",
"size" : 38274221,
"contentType" : "audio/mpeg",
"suffix" : "mp3",
"duration" : 2397,
"bitRate" : 128,
"isVideo" : false,
"playCount" : 0,
"created" : "2017-08-30T09:33:39.000Z",
"type" : "podcast",
"streamId" : "9982",
"channelId" : "2",
"description" : "Vaidehi decided to take on a year-long challenge. She'd pick a computer science topic every week, do tons of research and write a technical blog post explaining it in simple terms and beautiful illustrations. And then she actually did it. She tells us about her project, basecs, how it's changed her as a developer, and how she handles the trolls and negativity from people who don't appreciate her work. Show Notes Technical Writer position at CodeNewbie basecs 100 Days of Code Conway's Game of Life Hexes and Other Magical Numbers (Vaidehi's blog post) Bits, Bytes, Building With Binary (Vaidehi's blog post) Rust",
"status" : "completed",
"publishDate" : "2017-08-29T00:01:01.000Z"
}, {
"id" : "147",
"parent" : "9959",
"isDir" : false,
"title" : "S1:EP2 Building community in a virtual world: Moderation tools in VR (Cameron Brown)",
"album" : "CodeNewbie",
"artist" : "podcasts",
"coverArt" : "9959",
"size" : 52657014,
"contentType" : "audio/mpeg",
"suffix" : "mp3",
"duration" : 3298,
"bitRate" : 128,
"isVideo" : false,
"playCount" : 0,
"created" : "2017-08-25T19:32:53.000Z",
"type" : "podcast",
"streamId" : "9963",
"channelId" : "2",
"description" : "Rec Room is the most popular virtual reality game. It's a social space where you can play dodgeball, ping pong, darts and more with people from all over the world. But when you're inviting everyone to play, how do you make sure that everyone is safe? What happens when a player attacks someone? What does an attack even look like in a virtual world? Cameron Brown, Chief Creative Officer at Against Gravity, the creators of Rec Room, takes us through the world of social virtual reality and shows how they've designed a system to make their game a welcoming place for all. Show Links Incapsula (sponsor) Dice (sponsor) Technical Writer position at CodeNewbie HTC Vive Rec Room Rec Room's Code of Conduct",
"status" : "completed",
"publishDate" : "2017-08-24T00:01:01.000Z"
}, {
"id" : "146",
"parent" : "9959",
"isDir" : false,
"title" : "S1:EP1 Intro to Accessibility (Stephanie Slattery)",
"album" : "CodeNewbie",
"artist" : "podcasts",
"coverArt" : "9959",
"size" : 50708305,
"contentType" : "audio/mpeg",
"suffix" : "mp3",
"duration" : 3176,
"bitRate" : 128,
"isVideo" : false,
"playCount" : 0,
"created" : "2017-08-16T19:32:53.000Z",
"type" : "podcast",
"streamId" : "9962",
"channelId" : "2",
"description" : "We kick off the first episode of our official first season with Stephanie Slattery, a front-end engineer who specializes in accessibility. She breaks down the world of accessibility, giving you the perfect introduction to this topic. She explains the five categories of disabilities, shows us how to implement suggestions from the Web Content Accessibility Guidelines, and shares why shes so passionate about helping more people experience tech. Show Links Incapsula (sponsor) Hover (sponsor) An Introduction to Web Accessibility (Stephanie's Blog Post) Codeland, CodeNewbie's conference - April 21 & 22 in NYC NeoPets Dev Bootcamp Illinois Institute of Technology W3C WCAG (Web Content Accessibility Guidelines) ADA 1990 Rehabilitation Act of 1973",
"status" : "completed",
"publishDate" : "2017-08-16T00:01:01.000Z"
}, {
"id" : "0",
"parent" : "9959",
"isDir" : false,
"title" : "Ep. 146 Codeland - Mentorship, Technical Blogging, and Open Source Talks from Katrina Owen, Quincy Larson, and Nell Shamrell-Harrington",
"album" : "CodeNewbie",
"artist" : "podcasts",
"coverArt" : "9959",
"size" : 47779050,
"contentType" : "audio/mpeg",
"suffix" : "mp3",
"duration" : 2993,
"bitRate" : 128,
"isVideo" : false,
"playCount" : 0,
"created" : "2017-08-12T18:40:06.000Z",
"type" : "podcast",
"streamId" : "9960",
"channelId" : "2",
"description" : "In our final episode of our Codeland mini-series, Katrina Owen shares what it really takes to get that mentor you've always wanted, Quincy Larson gives us his best practices for writing technical blog posts people will actually read, and Nell Shamrell-Harrington explores what it really takes for an open source project to be successful and what you should know as a future contributor. Show Links Flatiron School (sponsor) Incapsula (sponsor) Hover (sponsor) CodeNewbie YouTube channel Codeland, CodeNewbie's conference - April 21 & 22 in NYC Be Lucky—its an easy skill to learn by Richard Wiseman How to read Medium articles people will actually read Sample Contribution Guide Sample Testing Guide Travis CI Sample Code of Conduct Open Source Governance Continuous Integration (CI) System",
"status" : "completed",
"publishDate" : "2017-08-01T00:01:01.000Z"
}, {
"id" : "1",
"isDir" : false,
"title" : "Ep. 145 Codeland - NYPL and Khan Academy talks from Courteney Ervin and Celia La",
"channelId" : "2",
"description" : "Courteney Ervin shares the ups and downs of building a product for one of the largest library systems in the world. Celia La walks us through the technical challenges (and solutions) of bringing Khan Academy's high quality content to people all over the world. Show Links Flatiron School (sponsor) Hover (sponsor) Incapsula (sponsor) CodeNewbie YouTube channel Codeland, CodeNewbie's conference - April 21 & 22 in NYC Khan Academy Memcached Git Version Control System New York Public Library Integrated Library System",
"status" : "skipped",
"publishDate" : "2017-07-25T00:01:01.000Z"
}, {
"id" : "2",
"isDir" : false,
"title" : "Ep. 144 Codeland - Accessibility and Education talks from Sterling Walker and Maurice Rogers",
"channelId" : "2",
"description" : "We wrap up our community talks with Sterlings story of her very first project at her first dev job: making the app accessible to two blind students. Maurice kicks off our education talks with the story of Abacus, his side project that became the learning system used by thousands of students in his country of Belize. Show Links Flatiron School (sponsor) Hover (sponsor)Incapsula (sponsor) CodeNewbie YouTube channel Codeland, CodeNewbie's conference - April 21 & 22 in NYC An Alphabet of Accessibility Issues Web Content Accessibility Guidelines (WCAG) Abacus Grails Java xkcd comic \"Standards\"",
"status" : "skipped",
"publishDate" : "2017-07-18T00:01:01.000Z"
}, {
"id" : "3",
"isDir" : false,
"title" : "Ep. 143 Codeland - Community Talks from Valerie Woolard Srinivasan and Rapi Castillo",
"channelId" : "2",
"description" : "Valerie explores the importance of security in creating powerful and engaged communities, and breaks down three ways your code might be vulnerable. Rapi shares his story of creating a toy coding project in D3.js that sparked a movement and helped thousands of people become more politically engaged. Checkout the videos of these talks on the CodeNewbie YouTube channel. Show Links Flatiron School (sponsor) Hover (sponsor) Incapsula (sponsor) CodeNewbie YouTube channel Codeland, CodeNewbie's conference - April 21 & 22 in NYC Rapi's Talk [VIDEO] Valerie's Talk [VIDEO] Progressive Coders Network D3.js SQL mass assignment man in the middle SQL injection validating inputs sanitizing inputs strong parameters",
"status" : "skipped",
"publishDate" : "2017-07-06T00:01:01.000Z"
}, {
"id" : "4",
"isDir" : false,
"title" : "Ep. 142 Codeland - Codeland - Mental Health talks from Michelle Morales and Greg Baugues",
"channelId" : "2",
"description" : "This episode features two talks on mental health that explore two very different sides of this important topic. Michelles talk is a technical showcase of how her research project uses open source tools to better diagnose depression. Greg shares his personal struggles with ADHD and bipolar disorder, and how important it is for us to openly talk about mental health. Show Links Flatiron School (sponsor) Hover (sponsor) Incapsula (sponsor) CodeNewbie YouTube channel Codeland, CodeNewbie's conference - April 21 & 22 in NYC CUNY Graduate Center Tom Insel's TED talk on depression Audio/Visual Emotion and Depression Recognition dataset DAIC-WOZ Database Covarep OpenFace OpenMM IBM Watson Speech to Text Natural Language Processing Machine Learning Feature Extraction Automatic Speech Recognition ZocDoc 718-312-8335 (Greg's mental health resource number)",
"status" : "skipped",
"publishDate" : "2017-06-28T00:01:01.000Z"
}, {
"id" : "5",
"isDir" : false,
"title" : "Ep. 141 Codeland - Interview with NYC's first CTO (Minerva Tantoco)",
"channelId" : "2",
"description" : "When Minerva Tantoco was first offered the CTO position for New York City, she thought it was a prank. But in 2014, she became the citys first Chief Technology Officer. She sits down with Codelands emcee, Nikhil Paul, to talk about how she started her long, impressive tech career, what programming looked like back her coding days, and how she hopes tech will transform cities for the better. Show Links Flatiron School (sponsor) Hover (sponsor) Incapsula (sponsor) CodeNewbie YouTube channel Mayor de Blasios announcement Codeland, CodeNewbie's conference - April 21 & 22 in NYC",
"status" : "skipped",
"publishDate" : "2017-06-21T00:01:01.000Z"
}, {
"id" : "6",
"isDir" : false,
"title" : "Ep. 140 Codeland - Gaming and City Talks from Chris Algoo, Kate Rabinowitz, Eric Brelsford",
"channelId" : "2",
"description" : "Chris Algoo shares how he co-created “Breakup Squad,” the game where you have to keep two exes from getting back together. Kate Rabinowitz shows us how open data can help build powerful, insightful tools to better understand and improve your city. Eric Brelsford shares how he used mapping tools to help community members turn vacant lots into beautiful neighborhood spaces. Show Links Flatiron School (sponsor) Hover (sponsor) Incapsula (sponsor) Breakup Squad (trailer) Codeland, CodeNewbie's conference - April 21 & 22 in NYC CodeNewbie YouTube channel Unity Twine FMOD Open Game Art Freesound.org The Big List of Game Making Tools An Introduction to Statistical Learning Interactive Data Visualization for the Web Code for America Brigades DataKind Maptime NYC Urban Reviewer 596 Acres Living Lots NYC NYCommons Open Data R Python Tableau Carto D3 API",
"status" : "skipped",
"publishDate" : "2017-06-13T00:01:01.000Z"
} ]
} ]
}
}
}

View File

@ -7,6 +7,7 @@ import org.moire.ultrasonic.api.subsonic.response.GetIndexesResponse
import org.moire.ultrasonic.api.subsonic.response.GetMusicDirectoryResponse
import org.moire.ultrasonic.api.subsonic.response.GetPlaylistResponse
import org.moire.ultrasonic.api.subsonic.response.GetPlaylistsResponse
import org.moire.ultrasonic.api.subsonic.response.GetPodcastsResponse
import org.moire.ultrasonic.api.subsonic.response.LicenseResponse
import org.moire.ultrasonic.api.subsonic.response.MusicFoldersResponse
import org.moire.ultrasonic.api.subsonic.response.SearchResponse
@ -108,4 +109,8 @@ interface SubsonicAPIDefinition {
@Query("public") public: Boolean? = null,
@Query("songIdToAdd") songIdsToAdd: List<Long>? = null,
@Query("songIndexToRemove") songIndexesToRemove: List<Int>? = null) : Call<SubsonicResponse>
@GET("getPodcasts.view")
fun getPodcasts(@Query("includeEpisodes") includeEpisodes: Boolean? = null,
@Query("id") id: Long? = null) : Call<GetPodcastsResponse>
}

View File

@ -27,4 +27,9 @@ data class MusicDirectoryChild(val id: Long = -1L,
val albumId: Long = -1,
val artistId: Long = -1,
val type: String = "",
val starred: Calendar? = null)
val starred: Calendar? = null,
val streamId: Long = -1,
val channelId: Long = -1,
val description: String = "",
val status: String = "",
val publishDate: Calendar? = null)

View File

@ -0,0 +1,14 @@
package org.moire.ultrasonic.api.subsonic.models
import com.fasterxml.jackson.annotation.JsonProperty
data class PodcastChannel(
val id: Long = -1,
val url: String = "",
val title: String = "",
val description: String = "",
val coverArt: String = "",
val originalImageUrl: String = "",
val status: String = "",
val errorMessage: String = "",
@JsonProperty("episode") val episodeList: List<MusicDirectoryChild> = emptyList())

View File

@ -0,0 +1,19 @@
package org.moire.ultrasonic.api.subsonic.response
import com.fasterxml.jackson.annotation.JsonProperty
import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions
import org.moire.ultrasonic.api.subsonic.SubsonicError
import org.moire.ultrasonic.api.subsonic.models.PodcastChannel
class GetPodcastsResponse(
status: Status,
version: SubsonicAPIVersions,
error: SubsonicError?) : SubsonicResponse(status, version, error) {
@JsonProperty("podcasts") private val channelsWrapper = PodcastChannelWrapper()
val podcastChannels: List<PodcastChannel>
get() = channelsWrapper.channelsList
}
private class PodcastChannelWrapper(
@JsonProperty("channel") val channelsList: List<PodcastChannel> = emptyList())