├── .gitignore ├── .project ├── .travis.yml ├── LICENSE.txt ├── README.md ├── library └── com.soundcloud.api-1.3.1-all.jar ├── pom.xml ├── repo └── com │ └── soundcloud │ └── api │ ├── 1.3.1-all │ ├── api-1.3.1-all.jar │ ├── api-1.3.1-all.jar.md5 │ ├── api-1.3.1-all.jar.sha1 │ ├── api-1.3.1-all.pom │ ├── api-1.3.1-all.pom.md5 │ └── api-1.3.1-all.pom.sha1 │ ├── maven-metadata-local.xml │ ├── maven-metadata-local.xml.md5 │ └── maven-metadata-local.xml.sha1 ├── src ├── main │ └── java │ │ └── de │ │ └── voidplus │ │ └── soundcloud │ │ ├── Comment.java │ │ ├── Group.java │ │ ├── Playlist.java │ │ ├── SoundCloud.java │ │ ├── Track.java │ │ └── User.java └── test │ └── java │ └── de │ └── voidplus │ └── soundcloud │ └── SoundCloudTest.java └── target ├── soundcloud-0.2.1-jar-with-dependencies.jar └── soundcloud-0.2.1.jar /.gitignore: -------------------------------------------------------------------------------- 1 | # os files 2 | Thumbs.db 3 | Desktop.ini 4 | .DS_Store 5 | .svn 6 | ._* 7 | .Spotlight-V100 8 | .Trashes 9 | 10 | # java 11 | .classpath 12 | 13 | # eclipse 14 | .metadata 15 | .settings 16 | 17 | # intellij 18 | *.iml 19 | .idea/ 20 | *.ipr 21 | *.iws 22 | out/ 23 | .idea_modules/ 24 | com_crashlytics_export_strings.xml 25 | crashlytics.properties 26 | crashlytics-build.properties 27 | 28 | # project 29 | target/archive-tmp 30 | target/classes 31 | target/generated-sources 32 | target/generated-test-sources 33 | target/maven-archiver 34 | target/maven-status 35 | target/surefire-reports 36 | target/test-classes 37 | target/MANIFEST.MF 38 | 39 | # sensitive env settings 40 | src/test/java/de/voidplus/soundcloud/Settings.java -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | soundcloud-java-library 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | branches: 3 | only: 4 | - dev 5 | - master 6 | jdk: 7 | - oraclejdk8 8 | - oraclejdk7 9 | - openjdk6 10 | - openjdk7 11 | - oraclejdk7 12 | env: 13 | global: 14 | - secure: CkTpaU75H56w7/9FKhVPOfFe7SRdmnKNe2IrMTDhOwoVA52gPDhX5Z8K2Aql01QF/FtciqAW3ZtzjMUqQWBQmYSaIf47JuRIs2pHFvb+hBVkc1WjNiKzyR8JZQXv73kYiAKoauYhaQBRGWVo+VP1W7tr1w4q7oWpQqhFRnkE4wQ= 15 | - secure: fxwa1xU9OF+0JRkX8jovLMDM+4Wm0Yz1uLAgwZ5jJ7JUm9kw7VnLvguECtBs/gSgpeTnXFd6Sfk2Er9MdinXfNRyrA0aetx3VEHBXB7CzX7YXdCRj1OrBv/XpR2FtAHXSnFYaSS7K03nZFwZq/upUmCrIQCsxrCn6SYXgmHkM8k= 16 | - secure: ApirEqwtUB+uE4fP9Qwa2iJ4XEtmw3eH7WlBa3OlAsTQ9+GfJGXKhW0IMByHyXtCeKWN+6zdZZP+Kb0Y1yA87dU5fUFmeUkvbQVFs5NyC9e8cJpea2htxH6HhypNm01xhZ5I8X/BZxj0bZfwhkQVjaVnElJfoR9wv6gWgj33QPQ= 17 | - secure: i+l02Eke63nMmWN/u3hDAZ7q3ljASK2SYPDp9xF3ou9JZgl6HYRvFdTWRgtxU03TXGlaK7fEFFc8AOG3Lx27peiPvhRwp0LfQd2ehl3Gg1ry/6mVGdffw7I3z5wBceH0yb9KkMXtqBsKLE74xSx6CkPM9d7QHL1U7PILMO5g3qQ= 18 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2012-2015, Darius Morawiec (http://voidplus.de/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SoundCloud Java library [![Build Status](https://travis-ci.org/nok/soundcloud-java-library.svg?branch=dev)](https://travis-ci.org/nok/soundcloud-java-library) 2 | 3 | Unofficial Java library, which simplifies the use of the official [SoundCloud Java API wrapper](https://github.com/soundcloud/java-api-wrapper). 4 | 5 | 6 | ## Table of Contents 7 | 8 | - [**Notice**](#notice) 9 | - [Download](#download) 10 | - [Dependencies](#dependencies) 11 | - [Usage](#usage) 12 | - [Initialization](#initialization) 13 | - [API](#api) 14 | - [REST](#rest) 15 | - [GET](#get) 16 | - [PUT](#put) 17 | - [POST](#post) 18 | - [DELETE](#delete) 19 | - [Examples](#examples) 20 | - [Processing](#processing) 21 | - [Questions?](#questions) 22 | - [License](#license) 23 | 24 | 25 | ## Notice 26 | 27 | **SoundCloud [dropped the support](https://github.com/soundcloud/java-api-wrapper#important-notice) for the official [SoundCloud Java API wrapper](https://github.com/soundcloud/java-api-wrapper), which is a primary dependency.** 28 | 29 | 30 | ## Download 31 | 32 | - [soundcloud-0.2.1-jar-with-dependencies.jar](target/soundcloud-0.2.1-jar-with-dependencies.jar?raw=true) (see the list of [dependencies](#dependencies)) 33 | - [soundcloud-0.2.1.jar](target/soundcloud-0.2.1.jar?raw=true) 34 | 35 | 36 | ## Dependencies 37 | 38 | Open and read the [pom.xml file](pom.xml) for all necessary dependencies. 39 | 40 | There are several internal dependencies: 41 | 42 | - [java-api-wrapper-1.3.1-all.jar](https://github.com/soundcloud/java-api-wrapper/) (```gradle jarAll```) by [SoundCloud](https://github.com/soundcloud) 43 | - [com.google.code.gson](http://code.google.com/p/google-gson/) by [Google](https://github.com/google) 44 | - [com.googlecode.json-simple](http://code.google.com/p/json-simple/) 45 | 46 | 47 | ## Usage 48 | 49 | ### Initialization 50 | 51 | Add the library jar to your classpath, import it and create a new instance of `SoundCloud`. Finally connect with specified [application settings](http://soundcloud.com/you/apps) and your personal [login](https://soundcloud.com/login/forgot) data. 52 | 53 | ```java 54 | import de.voidplus.soundcloud.*; 55 | ``` 56 | ```java 57 | SoundCloud soundcloud = new SoundCloud( 58 | "appClientId", 59 | "appClientSecret" 60 | ); 61 | 62 | // Or, if you need any permissions: 63 | 64 | SoundCloud soundcloud = new SoundCloud( 65 | "appClientId", 66 | "appClientSecret", 67 | "userLoginMail", 68 | "userLoginPass" 69 | ); 70 | 71 | // Or: 72 | 73 | SoundCloud soundcloud = new SoundCloud( 74 | "appClientId", 75 | "appClientSecret" 76 | ); 77 | soundcloud.login( 78 | "userLoginMail", 79 | "userLoginPass" 80 | ); 81 | ``` 82 | 83 | ### API 84 | 85 | The service of [Apigee](https://apigee.com/embed/console/soundcloud) is proper for learning and testing the official [SoundCloud API](http://developers.soundcloud.com/docs/api/reference). All API calls are mapped to REST methods: 86 | 87 | ```java 88 | public get( String path [, String[] filters] ) :T // GET 89 | public put( String path [, Object value] ) :T // PUT 90 | public post( String path, Object value ) :T // POST 91 | public delete( String path ) Boolean // DELETE 92 | ``` 93 | 94 | ### REST 95 | 96 | You can use the following API calls and/or helpers ("→" ⇔ HTTP 303 See Other Redirect): 97 | 98 | #### GET 99 | 100 | User[.java](src/de/voidplus/soundcloud/User.java): 101 | 102 | ```java 103 | User get("me") // /me 104 | getMe() 105 | 106 | ArrayList get("users") // /users 107 | getUsers([Integer offset, Integer limit]) 108 | 109 | User get("users/{contact_id}") // /users/{contact_id} 110 | getUser({contact_id}) 111 | 112 | ArrayList get("me/followings") // /me/followings 113 | getMeFollowing([Integer offset, Integer limit]) 114 | User get("me/followings/{contact_id}") // /me/followings/{contact_id} 115 | getMeFollowing({contact_id}) // → /users/{contact_id} 116 | 117 | ArrayList get("me/followers") // /me/followers 118 | getMeFollowers([Integer offset, Integer limit]) 119 | User get("me/followers/{contact_id}") // /me/followers/{contact_id} 120 | getMeFollower({contact_id}) // → /users/{contact_id} 121 | 122 | ArrayList get("groups/{group_id}/users") // /groups/{group_id}/users 123 | ArrayList get("groups/{group_id}/moderators") // /groups/{group_id}/moderators 124 | ArrayList get("groups/{group_id}/members") // /groups/{group_id}/members 125 | ArrayList get("groups/{group_id}/contributors") // /groups/{group_id}/contributors 126 | // 2271 = SoundCloud Sweetness ;) 127 | ``` 128 | 129 | Track[.java](src/de/voidplus/soundcloud/Track.java): 130 | 131 | ```java 132 | Track get("tracks/{track_id}") // /tracks/{track_id} 133 | getTrack({track_id}) 134 | 135 | ArrayList get("tracks") // /tracks 136 | getTracks([Integer offset, Integer limit]) 137 | 138 | ArrayList get("me/tracks") // /me/tracks 139 | getMeTracks([Integer offset, Integer limit]) 140 | 141 | ArrayList get("me/favorites") // /me/favorites 142 | getMeFavorites([Integer offset, Integer limit]) 143 | 144 | ArrayList get("groups/{group_id}/tracks") // /groups/{group_id}/tracks 145 | getTracksFromGroup({group_id}) 146 | ``` 147 | 148 | Playlist[.java](src/de/voidplus/soundcloud/Playlist.java): 149 | 150 | ```java 151 | Playlist get("playlists/{playlist_id}") // /playlists/{playlist_id} 152 | getPlaylist({playlist_id}) 153 | 154 | ArrayList get("playlists") // /playlists 155 | getPlaylists([Integer offset, Integer limit]) 156 | 157 | ArrayList get("me/playlists") // /me/playlists 158 | getMePlaylists([Integer offset, Integer limit]) 159 | ``` 160 | 161 | Group[.java](src/de/voidplus/soundcloud/Group.java): 162 | 163 | ```java 164 | Group get("groups/{group_id}") // /groups/{group_id} 165 | getGroup({group_id}) 166 | 167 | ArrayList get("groups") // /groups 168 | getGroups([Integer offset, Integer limit]) 169 | 170 | ArrayList get("me/groups") // /me/groups 171 | getMeGroups([Integer offset, Integer limit]) 172 | ``` 173 | 174 | Comment[.java](src/de/voidplus/soundcloud/Comment.java): 175 | 176 | ```java 177 | ArrayList get("me/comments") // /me/comments 178 | getMeComments([Integer offset, Integer limit]) 179 | 180 | ArrayList get("tracks/{track_id}/comments") // /tracks/{track_id}/comments 181 | getCommentsFromTrack({track_id}) 182 | ``` 183 | 184 | #### PUT 185 | 186 | User[.java](src/de/voidplus/soundcloud/User.java): 187 | 188 | ```java 189 | User put("me", User user) // /me 190 | putMe(User user) 191 | ``` 192 | 193 | Track[.java](src/de/voidplus/soundcloud/Track.java): 194 | 195 | ```java 196 | Track put("tracks/{track_id}", Track track) // /tracks/{track_id} 197 | 198 | Boolean put("me/favorites/{track_id}") // /me/favorites/{track_id} 199 | putFavoriteTrack({track_id}) 200 | ``` 201 | 202 | #### POST 203 | 204 | Track[.java](src/de/voidplus/soundcloud/Track.java): 205 | 206 | ```java 207 | Track post("tracks", Track track)) // /tracks 208 | postTrack(Track track) 209 | ``` 210 | 211 | Comment[.java](src/de/voidplus/soundcloud/Comment.java): 212 | 213 | ```java 214 | Comment post("tracks/{track_id}/comments", Comment comment) // /tracks/{track_id}/comments 215 | postCommentToTrack({track_id}, Comment comment) 216 | ``` 217 | 218 | #### DELETE 219 | 220 | User[.java](src/de/voidplus/soundcloud/User.java): 221 | 222 | ```java 223 | Boolean delete("me/followings/{contact_id}") // /me/followings/{contact_id} 224 | Boolean delete("users/{user_id}/followings/{contact_id}") // /users/{user_id}/followings/{contact_id} 225 | ``` 226 | 227 | Track[.java](src/de/voidplus/soundcloud/Track.java): 228 | 229 | ```java 230 | Boolean delete("tracks/{track_id}") // /tracks/{track_id} 231 | deleteTrack({track_id}) 232 | 233 | Boolean delete("me/favorites/{track_id}") // /me/favorites/{track_id} 234 | deleteFavoriteTrack({track_id}) 235 | 236 | Boolean delete("users/{user_id}/favorites/{track_id}") // /users/{user_id}/favorites/{track_id} 237 | ``` 238 | 239 | ## Examples 240 | 241 | ### User & Me 242 | 243 | Read user details: 244 | 245 | ```java 246 | User me = soundcloud.getMe(); 247 | System.out.println(me); 248 | 249 | System.out.println("ID: "+me.getId()); 250 | System.out.println("Username: "+me.getUsername()); 251 | System.out.println("Avatar-URL: "+me.getAvatarUrl()); 252 | ``` 253 | 254 | Update user details: 255 | 256 | ```java 257 | User me = soundcloud.getMe(); 258 | // OR 259 | // me = soundcloud.get("me"); 260 | 261 | me.setCity("Berlin"); 262 | me.setCountry("Germany"); 263 | me.setDescription("Text of description."); 264 | me.setWebsite("http://www.soundcloud.de/"); 265 | me.setWebsiteTitle("SoundCloud"); 266 | 267 | me = soundcloud.putMe(me); 268 | // OR 269 | // me = soundcloud.put("me", me); 270 | 271 | System.out.println(me); 272 | ``` 273 | 274 | Which sound do you like? Show all your favorites: 275 | 276 | ```java 277 | User me = soundcloud.getMe(); 278 | 279 | Integer count = me.getPublicFavoritesCount(); 280 | Integer limit = 50; // = max 281 | Integer pages = ((int)count/limit)+1; 282 | 283 | ArrayList all_tracks = new ArrayList(); 284 | 285 | for(int i=0; i temp_tracks = soundcloud.getMeFavorites((i*limit),limit); 287 | // OR 288 | // ArrayList temp_tracks = soundcloud.get("me/favorites", new String[] { 289 | // "order", "created_at", 290 | // "offset", Integer.toString(i*limit), 291 | // "limit", Integer.toString(limit) 292 | // }); 293 | 294 | all_tracks.addAll(temp_tracks); 295 | } 296 | for(Track track : all_tracks){ 297 | System.out.println(track.getTitle()+" (#"+track.getId()+")"); 298 | } 299 | ``` 300 | 301 | Like ~ Add a new track to your favorites: 302 | 303 | ```java 304 | ArrayList tracks = soundcloud.getTracks(0,3); 305 | // OR 306 | // ArrayList tracks = soundcloud.get("tracks", new String[] { 307 | // "order", "created_at", 308 | // "offset", "0", 309 | // "limit", "3" 310 | // }); 311 | 312 | Track track = tracks.get(0); // = ~random 313 | 314 | Boolean add = soundcloud.putFavoriteTrack(track.getId()); 315 | // OR 316 | // Boolean add = soundcloud.put("me/favorites/"+track.getId()); 317 | ``` 318 | 319 | Unlike ~ Remove a track from your favorites: 320 | 321 | ```java 322 | Boolean removing = soundcloud.deleteFavoriteTrack(72688617); 323 | // OR 324 | // Boolean removing = soundcloud.delete("me/favorites/72688617") 325 | 326 | if(removing){ 327 | System.out.println("Successful removing."); 328 | } 329 | ``` 330 | 331 | ### Track 332 | 333 | Upload a new track: 334 | 335 | ```java 336 | Track track = soundcloud.postTrack(new Track("titel of the song", "path/to/file.mp3")); 337 | // OR 338 | // Track track = soundcloud.post("tracks", new Track("titel of the song!", "path/to/file.mp3")); 339 | 340 | System.out.println(track.getTitle()+" (#"+track.getId()+")"); 341 | ``` 342 | 343 | Delete a track (Bad example, because we love your music!): 344 | 345 | ```java 346 | Boolean deletion = soundcloud.deleteTrack(track.getId()); 347 | // OR 348 | // Boolean deletion = soundcloud.delete("tracks/"+track.getId()); 349 | 350 | if(deletion){ 351 | System.out.println("Successful deletion."); 352 | } 353 | ``` 354 | 355 | List the last ten streamable tracks: 356 | 357 | ```java 358 | ArrayList streamable_tracks = soundcloud.get("tracks", new String[] { 359 | "order","created_at", 360 | "filter","streamable", 361 | "limit","10" 362 | }); 363 | 364 | for(Track track : streamable_tracks){ 365 | System.out.println(track.getTitle()+" (#"+track.getId()+")"); 366 | } 367 | ``` 368 | 369 | ### Group 370 | 371 | Get the moderators of a group: 372 | 373 | ```java 374 | ArrayList moderators = soundcloud.get("groups/2271/moderators"); 375 | for(User user : moderators){ 376 | System.out.println(user.getId()); 377 | } 378 | ``` 379 | 380 | ### Comment 381 | 382 | Post a new comment: 383 | 384 | ```java 385 | Comment comment = new Comment("Nice track!"); // new Comment("Nice track!", 120) // +timestamp 386 | 387 | comment = soundcloud.postCommentToTrack(70734856, comment); 388 | // OR 389 | // comment = soundcloud.post("tracks/70734856/comments", comment); 390 | 391 | System.out.println(comment); 392 | ``` 393 | 394 | ### Search 395 | 396 | Search track: 397 | 398 | ```java 399 | ArrayList result = soundcloud.findTrack("Chromatics"); 400 | if(result!=null){ 401 | System.out.println("Tracks: "+result.size()); 402 | for(Track track:result){ 403 | System.out.println(track); 404 | } 405 | } 406 | ``` 407 | 408 | Search user: 409 | 410 | ```java 411 | ArrayList result = soundcloud.findUser("damovi"); 412 | if(result!=null){ 413 | System.out.println("Users: "+result.size()); 414 | } 415 | ``` 416 | 417 | Search group: 418 | 419 | ```java 420 | ArrayList result = soundcloud.findGroup("SoundCloud"); 421 | if(result!=null){ 422 | System.out.println("Groups: "+result.size()); 423 | } 424 | ``` 425 | 426 | 427 | ## Questions? 428 | 429 | Don't be shy and feel free to contact me on Twitter: [@darius_morawiec](https://twitter.com/darius_morawiec) 430 | 431 | 432 | ## License 433 | 434 | [MIT License by SoundCloud](https://raw.github.com/soundcloud/java-api-wrapper/master/LICENSE). The library is Open Source Software released under the [MIT License](MIT-LICENSE.txt). 435 | 436 | --- 437 | 438 | ## Processing 439 | 440 | You can find the **SoundCloud for Processing** library in a [separate repository](https://github.com/nok/soundcloud-processing). That library is the core dependency of it. -------------------------------------------------------------------------------- /library/com.soundcloud.api-1.3.1-all.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nok/soundcloud-java-library/ce05aac18ab5fb2a420e32a81986b67da50885a5/library/com.soundcloud.api-1.3.1-all.jar -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | de.voidplus 5 | soundcloud 6 | 0.2.1 7 | 8 | 9 | repo 10 | file://${project.basedir}/repo 11 | 12 | 13 | 14 | 15 | com.google.code.gson 16 | gson 17 | 2.3 18 | 19 | 20 | com.googlecode.json-simple 21 | json-simple 22 | 1.1.1 23 | 24 | 25 | org.apache.httpcomponents 26 | httpclient 27 | 4.3.6 28 | 29 | 32 | 33 | com.soundcloud 34 | api 35 | 1.3.1-all 36 | 37 | 38 | org.mockito 39 | mockito-all 40 | 1.10.19 41 | test 42 | 43 | 44 | 45 | 46 | 47 | org.apache.maven.plugins 48 | maven-jar-plugin 49 | 2.4 50 | 51 | 52 | org.apache.maven.plugins 53 | maven-assembly-plugin 54 | 55 | 56 | jar-with-dependencies 57 | 58 | 59 | 60 | 61 | package 62 | 63 | single 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /repo/com/soundcloud/api/1.3.1-all/api-1.3.1-all.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nok/soundcloud-java-library/ce05aac18ab5fb2a420e32a81986b67da50885a5/repo/com/soundcloud/api/1.3.1-all/api-1.3.1-all.jar -------------------------------------------------------------------------------- /repo/com/soundcloud/api/1.3.1-all/api-1.3.1-all.jar.md5: -------------------------------------------------------------------------------- 1 | 2ec62e7254be6ca7303379314b243b68 -------------------------------------------------------------------------------- /repo/com/soundcloud/api/1.3.1-all/api-1.3.1-all.jar.sha1: -------------------------------------------------------------------------------- 1 | ba525800209191f3dfc1fb48fe02f8a14a2db220 -------------------------------------------------------------------------------- /repo/com/soundcloud/api/1.3.1-all/api-1.3.1-all.pom: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.soundcloud 6 | api 7 | 1.3.1-all 8 | POM was created from install:install-file 9 | 10 | -------------------------------------------------------------------------------- /repo/com/soundcloud/api/1.3.1-all/api-1.3.1-all.pom.md5: -------------------------------------------------------------------------------- 1 | 1a84363325e38fb33282a4d93e2dc21d -------------------------------------------------------------------------------- /repo/com/soundcloud/api/1.3.1-all/api-1.3.1-all.pom.sha1: -------------------------------------------------------------------------------- 1 | be9cd6217eaea1b55f97175af0abb31964287853 -------------------------------------------------------------------------------- /repo/com/soundcloud/api/maven-metadata-local.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | com.soundcloud 4 | api 5 | 6 | 1.3.1-all 7 | 8 | 1.3.1-all 9 | 10 | 20141122214234 11 | 12 | 13 | -------------------------------------------------------------------------------- /repo/com/soundcloud/api/maven-metadata-local.xml.md5: -------------------------------------------------------------------------------- 1 | 475ae29e0707ef46b5afcd74967a4fbb -------------------------------------------------------------------------------- /repo/com/soundcloud/api/maven-metadata-local.xml.sha1: -------------------------------------------------------------------------------- 1 | f52db45707509dbf77fbb6dae7a0454b98f49ec1 -------------------------------------------------------------------------------- /src/main/java/de/voidplus/soundcloud/Comment.java: -------------------------------------------------------------------------------- 1 | package de.voidplus.soundcloud; 2 | 3 | public class Comment { 4 | 5 | private Integer id; 6 | private String created_at; 7 | private Integer user_id; 8 | private Integer track_id; 9 | private Integer timestamp; 10 | private String body; 11 | private String uri; 12 | private User user; 13 | 14 | public Comment() 15 | { 16 | } 17 | 18 | public Integer getId() { 19 | return id; 20 | } 21 | 22 | public String getBody() { 23 | return body; 24 | } 25 | 26 | public void setBody(String body) { 27 | this.body = body; 28 | } 29 | 30 | public String getCreatedAt() { 31 | return created_at; 32 | } 33 | 34 | public Integer getTrackId() { 35 | return track_id; 36 | } 37 | 38 | public void setTimestamp(Integer secs) { 39 | this.timestamp = secs; 40 | } 41 | 42 | public Integer getTimestamp() { 43 | return timestamp; 44 | } 45 | 46 | public String getUri() { 47 | return uri; 48 | } 49 | 50 | public Integer getUserId() { 51 | return user_id; 52 | } 53 | 54 | public User getUser() { 55 | return user; 56 | } 57 | 58 | @Override 59 | public String toString() { 60 | return "Comment [id=" + id + ", created_at=" + created_at 61 | + ", user_id=" + user_id + ", track_id=" + track_id 62 | + ", timestamp=" + timestamp + ", body=" + body + ", uri=" 63 | + uri + ", user=" + user + "]"; 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /src/main/java/de/voidplus/soundcloud/Group.java: -------------------------------------------------------------------------------- 1 | package de.voidplus.soundcloud; 2 | 3 | public class Group { 4 | 5 | private Integer id; 6 | private String created_at; 7 | private String permalink; 8 | private String name; 9 | private String short_description; 10 | private String description; 11 | private String uri; 12 | private String permalink_url; 13 | private String artwork_url; 14 | private User creator; 15 | 16 | public Group() 17 | { 18 | } 19 | 20 | public Integer getId() { 21 | return id; 22 | } 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | public void setName(String name) { 29 | this.name = name; 30 | } 31 | 32 | public String getDescription() { 33 | return description; 34 | } 35 | 36 | public void setDescription(String description) { 37 | this.description = description; 38 | } 39 | 40 | public String getCreatedAt() { 41 | return created_at; 42 | } 43 | 44 | public String getPermalink() { 45 | return permalink; 46 | } 47 | 48 | public String getShortDescription() { 49 | return short_description; 50 | } 51 | 52 | public void setShortDescription(String short_description) { 53 | this.short_description = short_description; 54 | } 55 | 56 | public String getUri() { 57 | return uri; 58 | } 59 | 60 | public String getPermalinkUrl() { 61 | return permalink_url; 62 | } 63 | 64 | public String getArtworkUrl() { 65 | return artwork_url; 66 | } 67 | 68 | public User getCreator() { 69 | return creator; 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | return "Group [id=" + id + ", created_at=" + created_at 75 | + ", permalink=" + permalink + ", name=" + name + ", uri=" 76 | + uri + ", permalink_url=" + permalink_url + ", artwork_url=" 77 | + artwork_url + ", creator=" + creator + "]"; 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /src/main/java/de/voidplus/soundcloud/Playlist.java: -------------------------------------------------------------------------------- 1 | package de.voidplus.soundcloud; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class Playlist { 6 | 7 | private Integer id; 8 | private String created_at; 9 | private Integer user_id; 10 | private User user; 11 | private Integer duration; 12 | private String sharing; 13 | private String tag_list; 14 | private String permalink; 15 | private String description; 16 | private Boolean streamable; 17 | private Boolean downloadable; 18 | private String genre; 19 | private String release; 20 | private String purchase_url; 21 | private Integer label_id; 22 | private String label_name; 23 | private String type; 24 | private String playlist_type; 25 | private Integer ean; 26 | private String title; 27 | private Integer release_year; 28 | private Integer release_month; 29 | private Integer release_day; 30 | private String license; 31 | private String uri; 32 | private String permalink_url; 33 | private String artwork_url; 34 | private ArrayList tracks; 35 | 36 | public Playlist() 37 | { 38 | } 39 | 40 | public Integer getId() { 41 | return id; 42 | } 43 | 44 | public String getGenre() { 45 | return genre; 46 | } 47 | 48 | public void setGenre(String genre) { 49 | this.genre = genre; 50 | } 51 | 52 | public String getTitle() { 53 | return title; 54 | } 55 | 56 | public void setTitle(String title) { 57 | this.title = title; 58 | } 59 | 60 | public String getCreatedAt() { 61 | return created_at; 62 | } 63 | 64 | public Integer getUserId() { 65 | return user_id; 66 | } 67 | 68 | public User getUser() { 69 | return user; 70 | } 71 | 72 | public Integer getDuration() { 73 | return duration; 74 | } 75 | 76 | public String getSharing() { 77 | return sharing; 78 | } 79 | 80 | public String getTagList() { 81 | return tag_list; 82 | } 83 | 84 | public String getPermalink() { 85 | return permalink; 86 | } 87 | 88 | public String getDescription() { 89 | return description; 90 | } 91 | 92 | public Boolean isStreamable() { 93 | return streamable; 94 | } 95 | 96 | public Boolean isDownloadable() { 97 | return downloadable; 98 | } 99 | 100 | public String getRelease() { 101 | return release; 102 | } 103 | 104 | public String getPurchaseUrl() { 105 | return purchase_url; 106 | } 107 | 108 | public Integer getLabelId() { 109 | return label_id; 110 | } 111 | 112 | public String getLabelName() { 113 | return label_name; 114 | } 115 | 116 | public String getType() { 117 | return type; 118 | } 119 | 120 | public String getPlaylistType() { 121 | return playlist_type; 122 | } 123 | 124 | public Integer getEan() { 125 | return ean; 126 | } 127 | 128 | public Integer getReleaseYear() { 129 | return release_year; 130 | } 131 | 132 | public Integer getReleaseMonth() { 133 | return release_month; 134 | } 135 | 136 | public Integer getReleaseDay() { 137 | return release_day; 138 | } 139 | 140 | public String getLicense() { 141 | return license; 142 | } 143 | 144 | public String getUri() { 145 | return uri; 146 | } 147 | 148 | public String getPermalinkUrl() { 149 | return permalink_url; 150 | } 151 | 152 | public String getArtworkUrl() { 153 | return artwork_url; 154 | } 155 | 156 | public ArrayList getTracks() { 157 | return tracks; 158 | } 159 | 160 | @Override 161 | public String toString() { 162 | return "Playlist [id=" + id + ", created_at=" + created_at 163 | + ", user_id=" + user_id + ", user=" + user + ", duration=" 164 | + duration + ", sharing=" + sharing + ", tag_list=" + tag_list 165 | + ", permalink=" + permalink + ", description=" + description 166 | + ", streamable=" + streamable + ", downloadable=" 167 | + downloadable + ", genre=" + genre + ", release=" + release 168 | + ", purchase_url=" + purchase_url + ", label_id=" + label_id 169 | + ", label_name=" + label_name + ", type=" + type 170 | + ", playlist_type=" + playlist_type + ", ean=" + ean 171 | + ", title=" + title + ", release_year=" + release_year 172 | + ", release_month=" + release_month + ", release_day=" 173 | + release_day + ", license=" + license + ", uri=" + uri 174 | + ", permalink_url=" + permalink_url + ", artwork_url=" 175 | + artwork_url + ", tracks=" + tracks + "]"; 176 | } 177 | 178 | } -------------------------------------------------------------------------------- /src/main/java/de/voidplus/soundcloud/SoundCloud.java: -------------------------------------------------------------------------------- 1 | package de.voidplus.soundcloud; 2 | 3 | 4 | import com.google.gson.Gson; 5 | import com.soundcloud.api.*; 6 | import org.apache.http.HttpResponse; 7 | import org.apache.http.HttpStatus; 8 | import org.json.simple.JSONArray; 9 | import org.json.simple.parser.JSONParser; 10 | 11 | import java.io.File; 12 | import java.io.IOException; 13 | import java.util.ArrayList; 14 | import java.util.regex.Matcher; 15 | import java.util.regex.Pattern; 16 | 17 | 18 | public class SoundCloud { 19 | 20 | 21 | public static final String VERSION = "0.2.1"; 22 | 23 | 24 | public enum Type { 25 | USER, 26 | TRACK, 27 | PLAYLIST, 28 | COMMENT, 29 | GROUP 30 | } 31 | 32 | public enum Rest { 33 | GET, 34 | PUT, 35 | POST, 36 | DELETE 37 | } 38 | 39 | 40 | protected final String app_client_id; 41 | protected final String app_client_secret; 42 | 43 | protected Token token; 44 | protected ApiWrapper wrapper; 45 | 46 | protected JSONParser parser; 47 | protected Gson gson; 48 | 49 | 50 | /** 51 | * Constructor of the SoundCloud wrapper, which creates the API wrapper and generates the Access Token. 52 | * 53 | * @param _app_client_id Application Client ID 54 | * @param _app_client_secret Application Client Secret 55 | */ 56 | public SoundCloud(String _app_client_id, String _app_client_secret) { 57 | this.app_client_id = _app_client_id; 58 | this.app_client_secret = _app_client_secret; 59 | 60 | this.parser = new JSONParser(); 61 | this.gson = new Gson(); 62 | 63 | wrapper = new ApiWrapper(app_client_id, app_client_secret, null, null); 64 | wrapper.setToken(null); 65 | wrapper.setDefaultContentType("application/json"); 66 | } 67 | 68 | 69 | /** 70 | * Constructor of the SoundCloud wrapper, which creates the API wrapper and generates the Access Token. 71 | * 72 | * @param _app_client_id Application client ID 73 | * @param _app_client_secret Application client secret 74 | */ 75 | public SoundCloud(String _app_client_id, String _app_client_secret, String _login_name, String _login_password) { 76 | this(_app_client_id, _app_client_secret); 77 | this.login(_login_name, _login_password); 78 | } 79 | 80 | 81 | /** 82 | * Login to get a valid token. 83 | * 84 | * @param _login_name SoundCloud login name 85 | * @param _login_password SoundCloud login pass 86 | * @return Boolean state of login 87 | */ 88 | public boolean login(String _login_name, String _login_password) { 89 | try { 90 | this.token = wrapper.login(_login_name, _login_password, Token.SCOPE_NON_EXPIRING); 91 | } catch (IOException e) { 92 | e.printStackTrace(); 93 | return false; 94 | } 95 | return true; 96 | } 97 | 98 | /** 99 | * Filter API string. 100 | * 101 | * @param api 102 | * @return 103 | */ 104 | private String filterApiString(String api) { 105 | if (api.length() > 0) { 106 | // Suppressing / Forcing the `/.` at the beginning 107 | if (!api.startsWith("/")) { 108 | api = "/" + api; 109 | } 110 | // Removing the '/' at the end 111 | if (api.charAt(api.length() - 1) == '/') { 112 | api = api.substring(0, api.length() - 1); 113 | } 114 | // Define the format to ".json" 115 | api = api.replace(".format", ".json").replace(".xml", ".json"); 116 | if (api.indexOf(".json") == -1) { 117 | api += ".json"; 118 | } 119 | return api; 120 | } 121 | // TODO: throw exception if api string is empty 122 | return null; 123 | } 124 | 125 | /** 126 | * Define type of result. 127 | * 128 | * @param api 129 | * @return 130 | */ 131 | private Type defineApiType(String api) { 132 | Type type = null; 133 | if ( 134 | api.matches("^/me.json") || 135 | api.matches("^/me/(followings(/[0-9]+)?|followers(/[0-9]+)?).json") || 136 | api.matches("^/users(/[0-9]+)?.json") || 137 | api.matches("^/users/([0-9]+)/(followings|followers).json") || 138 | api.matches("^/groups/([0-9]+)/(users|moderators|members|contributors).json") 139 | ) { 140 | type = Type.USER; 141 | } else if ( 142 | api.matches("^/tracks(/[0-9]+)?.json") || 143 | api.matches("^/me/(tracks|favorites)(/[0-9]+)?.json") || 144 | api.matches("^/users/([0-9]+)/(tracks|favorites).json") 145 | ) { 146 | type = Type.TRACK; 147 | } else if ( 148 | api.matches("^/playlists(/[0-9]+)?.json") || 149 | api.matches("^/me/playlists.json") || 150 | api.matches("^/users/([0-9]+)/playlists.json") || 151 | api.matches("^/groups/([0-9]+)/tracks.json") 152 | ) { 153 | type = Type.PLAYLIST; 154 | } else if ( 155 | api.matches("^/comments/([0-9]+).json") || 156 | api.matches("^/me/comments.json") || 157 | api.matches("^/tracks/([0-9]+)/comments.json") 158 | ) { 159 | type = Type.COMMENT; 160 | } else if ( 161 | api.matches("^/groups(/[0-9]+)?.json") || 162 | api.matches("^/me/groups.json") || 163 | api.matches("^/users/([0-9]+)/groups.json") 164 | ) { 165 | type = Type.GROUP; 166 | } 167 | if (type == null) { 168 | // TODO: throw exception if type is invalid 169 | } 170 | return type; 171 | } 172 | 173 | /** 174 | * Append get arguments (e.g. filters) to API. 175 | * 176 | * @param api 177 | * @param args 178 | * @return 179 | */ 180 | private String appendGetArgs(String api, String[] args) { 181 | if (args != null) { 182 | if (args.length > 0 && args.length % 2 == 0) { 183 | api += "?"; 184 | for (int i = 0, l = args.length; i < l; i += 2) { 185 | if (i != 0) { 186 | api += "&"; 187 | } 188 | api += (args[i] + "=" + args[i + 1]); 189 | } 190 | if (this.token == null) { 191 | api += ("&consumer_key=" + this.app_client_id); 192 | } 193 | } 194 | } else { 195 | api += "?consumer_key=" + this.app_client_id; 196 | } 197 | return api; 198 | } 199 | 200 | /** 201 | * The core of the library. 202 | * 203 | * @param api 204 | * @param rest 205 | * @param value 206 | * @param filters 207 | * @param 208 | * @return 209 | */ 210 | private T api(String api, Rest rest, Object value, String[] filters) { 211 | api = this.filterApiString(api); 212 | Type type = this.defineApiType(api); 213 | api = this.appendGetArgs(api, filters); 214 | 215 | // TODO: execute each type of request in a separate method (get, post, put, delete) 216 | try { 217 | 218 | Request resource; 219 | HttpResponse response; 220 | String klass, content; 221 | 222 | switch (rest) { 223 | case GET: 224 | response = wrapper.get(Request.to(api)); 225 | 226 | if (response.getStatusLine().getStatusCode() == 303) { // recursive better? 227 | // System.out.println( "303: "+response.getFirstHeader("Location").getValue() ); 228 | api = (String) (response.getFirstHeader("Location").getValue() + ".json").replace("https://api.soundcloud.com", ""); 229 | response = wrapper.get(Request.to(api)); 230 | } 231 | 232 | if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 233 | String json = (String) (Http.formatJSON(Http.getString(response))).trim(); 234 | 235 | if (json.startsWith("[") && json.endsWith("]")) { 236 | JSONArray data = (JSONArray) parser.parse(json); 237 | 238 | if (data.size() > 0) { 239 | switch (type) { 240 | case USER: 241 | ArrayList users = new ArrayList(); 242 | for (int i = 0, l = data.size(); i < l; i++) { 243 | String tuple = data.get(i).toString(); 244 | User user = gson.fromJson(replaceJsonsBlank(tuple), User.class); 245 | users.add(user); 246 | } 247 | return (T) users; 248 | case TRACK: 249 | ArrayList tracks = new ArrayList(); 250 | for (int i = 0, l = data.size(); i < l; i++) { 251 | String tuple = data.get(i).toString(); 252 | Track track = gson.fromJson(replaceJsonsBlank(tuple), Track.class); 253 | track.setSoundCloud(this); 254 | tracks.add(track); 255 | } 256 | return (T) tracks; 257 | case PLAYLIST: 258 | ArrayList playlists = new ArrayList(); 259 | for (int i = 0, l = data.size(); i < l; i++) { 260 | String tuple = data.get(i).toString(); 261 | Playlist playlist = gson.fromJson(replaceJsonsBlank(tuple), Playlist.class); 262 | playlists.add(playlist); 263 | } 264 | return (T) playlists; 265 | case COMMENT: 266 | ArrayList comments = new ArrayList(); 267 | for (int i = 0, l = data.size(); i < l; i++) { 268 | String tuple = data.get(i).toString(); 269 | Comment comment = gson.fromJson(replaceJsonsBlank(tuple), Comment.class); 270 | comments.add(comment); 271 | } 272 | return (T) comments; 273 | case GROUP: 274 | ArrayList groups = new ArrayList(); 275 | for (int i = 0, l = data.size(); i < l; i++) { 276 | String tuple = data.get(i).toString(); 277 | Group group = gson.fromJson(replaceJsonsBlank(tuple), Group.class); 278 | groups.add(group); 279 | } 280 | return (T) groups; 281 | default: 282 | return null; 283 | } 284 | 285 | } 286 | 287 | } else { 288 | 289 | switch (type) { 290 | case USER: 291 | User user = gson.fromJson(replaceJsonsBlank(json), User.class); 292 | return (T) user; 293 | case TRACK: 294 | Track track = gson.fromJson(replaceJsonsBlank(json), Track.class); 295 | track.setSoundCloud(this); 296 | return (T) track; 297 | case PLAYLIST: 298 | Playlist playlist = gson.fromJson(replaceJsonsBlank(json), Playlist.class); 299 | return (T) playlist; 300 | case COMMENT: 301 | Comment comment = gson.fromJson(replaceJsonsBlank(json), Comment.class); 302 | return (T) comment; 303 | case GROUP: 304 | Group group = gson.fromJson(replaceJsonsBlank(json), Group.class); 305 | return (T) group; 306 | default: 307 | return null; 308 | } 309 | 310 | } 311 | } else { 312 | System.err.println("Invalid status received: " + response.getStatusLine()); 313 | } 314 | break; 315 | case POST: 316 | 317 | klass = value.getClass().getName(); 318 | klass = klass.substring((klass.lastIndexOf('.') + 1)); 319 | 320 | if (klass.equals("Track")) { 321 | Track track = ((Track) value); 322 | resource = Request.to(Endpoints.TRACKS) 323 | .add(Params.Track.TITLE, track.getTitle()) 324 | .add(Params.Track.TAG_LIST, track.getTagList()) 325 | .withFile(Params.Track.ASSET_DATA, new File(track.asset_data)); 326 | } else if (klass.equals("Comment")) { 327 | content = gson.toJson(value); 328 | content = "{\"comment\":" + content + "}"; 329 | resource = Request.to(api.replace(".json", "")) 330 | .withContent(content, "application/json"); 331 | } else { 332 | return null; 333 | } 334 | 335 | response = wrapper.post(resource); 336 | 337 | if (response.getStatusLine().getStatusCode() == HttpStatus.SC_CREATED) { 338 | String json = (String) (Http.formatJSON(Http.getString(response))).trim(); 339 | switch (type) { 340 | case TRACK: 341 | Track track = gson.fromJson(replaceJsonsBlank(json), Track.class); 342 | track.setSoundCloud(this); 343 | return (T) track; 344 | case COMMENT: 345 | Comment comment = gson.fromJson(replaceJsonsBlank(json), Comment.class); 346 | return (T) comment; 347 | default: 348 | return null; 349 | } 350 | 351 | } else { 352 | System.err.println("Invalid status received: " + response.getStatusLine()); 353 | } 354 | 355 | break; 356 | case PUT: 357 | 358 | if (value != null) { 359 | 360 | klass = value.getClass().getName(); 361 | klass = klass.substring((klass.lastIndexOf('.') + 1)); 362 | 363 | content = gson.toJson(value); 364 | 365 | if (klass.equals("User")) { 366 | content = "{\"user\":" + content + "}"; 367 | } else if (klass.equals("Track")) { 368 | content = "{\"track\":" + content + "}"; 369 | } else { 370 | return null; 371 | } 372 | 373 | resource = Request.to(api.replace(".json", "")).withContent(content, "application/json"); 374 | } else { 375 | resource = Request.to(api.replace(".json", "")); 376 | } 377 | 378 | response = wrapper.put(resource); 379 | 380 | if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 381 | String json = (String) (Http.formatJSON(Http.getString(response))).trim(); 382 | 383 | switch (type) { 384 | case USER: 385 | User user = gson.fromJson(replaceJsonsBlank(json), User.class); 386 | return (T) user; 387 | case TRACK: 388 | Track track = gson.fromJson(replaceJsonsBlank(json), Track.class); 389 | track.setSoundCloud(this); 390 | return (T) track; 391 | default: 392 | return null; 393 | } 394 | } else if (response.getStatusLine().getStatusCode() == HttpStatus.SC_CREATED) { 395 | return (T) new Boolean(true); 396 | } else { 397 | System.err.println("Invalid status received: " + response.getStatusLine()); 398 | } 399 | 400 | break; 401 | case DELETE: 402 | response = wrapper.delete(Request.to(api)); 403 | 404 | if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 405 | return (T) new Boolean(true); 406 | } 407 | return (T) new Boolean(false); 408 | } 409 | 410 | } catch (Exception e) { 411 | e.printStackTrace(); 412 | } 413 | return null; 414 | } 415 | 416 | 417 | /** 418 | * API access to GET (REST) data. 419 | * 420 | * @param api 421 | * @return 422 | */ 423 | public T get(String api) { 424 | return this.api(api, Rest.GET, null, null); 425 | } 426 | 427 | /** 428 | * API access with filters to GET (REST) data. 429 | * 430 | * @param api 431 | * @param filters 432 | * @return 433 | */ 434 | public T get(String api, String[] filters) { 435 | return this.api(api, Rest.GET, null, filters); 436 | } 437 | 438 | 439 | /** 440 | * API access to POST (REST) new data. 441 | * 442 | * @param api 443 | * @return 444 | */ 445 | public T post(String api, Object value) { 446 | return this.api(api, Rest.POST, value, null); 447 | } 448 | 449 | 450 | /** 451 | * API access to PUT (REST) new data. 452 | * 453 | * @param api 454 | * @return 455 | */ 456 | public T put(String api) { 457 | return this.api(api, Rest.PUT, null, null); 458 | } 459 | 460 | /** 461 | * API access to PUT (REST) new data. 462 | * 463 | * @param api 464 | * @return 465 | */ 466 | public T put(String api, Object value) { 467 | return this.api(api, Rest.PUT, value, null); 468 | } 469 | 470 | 471 | /** 472 | * API access to DELETE (REST) data. 473 | * 474 | * @param api 475 | * @return 476 | */ 477 | public Boolean delete(String api) { 478 | return (Boolean) this.api(api, Rest.DELETE, null, null); 479 | } 480 | 481 | 482 | /** 483 | * Get data about you. 484 | * 485 | * @return 486 | */ 487 | public User getMe() { 488 | return this.get("me"); 489 | } 490 | 491 | /** 492 | * Get your followings. 493 | * 494 | * @param offset 495 | * @param limit 496 | * @return 497 | */ 498 | public ArrayList getMeFollowings(Integer offset, Integer limit) { 499 | return this.get("me/followings", new String[]{ 500 | "limit", Integer.toString(limit), 501 | "offset", Integer.toString(offset) 502 | }); 503 | } 504 | 505 | /** 506 | * Get your last 50 followings. 507 | * 508 | * @return 509 | */ 510 | public ArrayList getMeFollowings() { 511 | return this.getMeFollowings(0, 50); 512 | } 513 | 514 | /** 515 | * Get a specific following. 516 | * 517 | * @param contact_id 518 | * @return 519 | */ 520 | public User getMeFollowing(Integer contact_id) { 521 | return this.get("me/followings/" + Integer.toString(contact_id)); 522 | } 523 | 524 | /** 525 | * Get your followers. 526 | * 527 | * @param offset 528 | * @param limit 529 | * @return 530 | */ 531 | public ArrayList getMeFollowers(Integer offset, Integer limit) { 532 | return this.get("me/followers", new String[]{ 533 | "limit", Integer.toString(limit), 534 | "offset", Integer.toString(offset) 535 | }); 536 | } 537 | 538 | /** 539 | * Get your last 50 followers. 540 | * 541 | * @return 542 | */ 543 | public ArrayList getMeFollowers() { 544 | return this.getMeFollowers(0, 50); 545 | } 546 | 547 | /** 548 | * Get a specific follower. 549 | * 550 | * @param contact_id 551 | * @return 552 | */ 553 | public User getMeFollower(Integer contact_id) { 554 | return this.get("me/followers/" + Integer.toString(contact_id)); 555 | } 556 | 557 | /** 558 | * Get your favorite tracks. 559 | * 560 | * @param limit 561 | * @param offset 562 | * @return 563 | */ 564 | public ArrayList getMeFavorites(Integer offset, Integer limit) { 565 | return this.get("me/favorites", new String[]{ 566 | "order", "created_at", 567 | "limit", Integer.toString(limit), 568 | "offset", Integer.toString(offset) 569 | }); 570 | } 571 | 572 | /** 573 | * Get your last 50 favorite tracks. 574 | * 575 | * @return 576 | */ 577 | public ArrayList getMeFavorites() { 578 | return this.getMeFavorites(0, 50); 579 | } 580 | 581 | /** 582 | * Get your last tracks. 583 | * 584 | * @param offset 585 | * @param limit 586 | * @return 587 | */ 588 | public ArrayList getMeTracks(Integer offset, Integer limit) { 589 | return this.get("me/tracks", new String[]{ 590 | "order", "created_at", 591 | "limit", Integer.toString(limit), 592 | "offset", Integer.toString(offset) 593 | }); 594 | } 595 | 596 | /** 597 | * Get your last 50 tracks. 598 | * 599 | * @return 600 | */ 601 | public ArrayList getMeTracks() { 602 | return this.getMeTracks(0, 50); 603 | } 604 | 605 | /** 606 | * Get your playlists. 607 | * 608 | * @return 609 | */ 610 | public ArrayList getMePlaylists(Integer offset, Integer limit) { 611 | return this.get("me/playlists", new String[]{ 612 | "order", "created_at", 613 | "limit", Integer.toString(limit), 614 | "offset", Integer.toString(offset) 615 | }); 616 | } 617 | 618 | /** 619 | * Get your last 50 playlists. 620 | * 621 | * @return 622 | */ 623 | public ArrayList getMePlaylists() { 624 | return this.getMePlaylists(0, 50); 625 | } 626 | 627 | /** 628 | * Get your groups. 629 | * 630 | * @return 631 | */ 632 | public ArrayList getMeGroups(Integer offset, Integer limit) { 633 | return this.get("me/groups", new String[]{ 634 | "order", "created_at", 635 | "limit", Integer.toString(limit), 636 | "offset", Integer.toString(offset) 637 | }); 638 | } 639 | 640 | /** 641 | * Get your last 50 groups. 642 | * 643 | * @return 644 | */ 645 | public ArrayList getMeGroups() { 646 | return this.getMeGroups(0, 50); 647 | } 648 | 649 | /** 650 | * Get your comments. 651 | * 652 | * @return 653 | */ 654 | public ArrayList getMeComments(Integer offset, Integer limit) { 655 | return this.get("me/comments", new String[]{ 656 | "order", "created_at", 657 | "limit", Integer.toString(limit), 658 | "offset", Integer.toString(offset) 659 | }); 660 | } 661 | 662 | /** 663 | * Get your last 50 comments. 664 | * 665 | * @return 666 | */ 667 | public ArrayList getMeComments() { 668 | return this.getMeComments(0, 50); 669 | } 670 | 671 | /** 672 | * Get comments from specific track. 673 | * 674 | * @param track_id 675 | * @return 676 | */ 677 | public ArrayList getCommentsFromTrack(Integer track_id) { 678 | return this.get("tracks/" + Integer.toString(track_id) + "/comments"); 679 | } 680 | 681 | /** 682 | * Get a specific playlist. 683 | * 684 | * @param playlist_id 685 | * @return 686 | */ 687 | public Playlist getPlaylist(Integer playlist_id) { 688 | return this.get("playlists/" + Integer.toString(playlist_id)); 689 | } 690 | 691 | /** 692 | * Get last playlists. 693 | * 694 | * @param offset 695 | * @param limit 696 | * @return 697 | */ 698 | public ArrayList getPlaylists(Integer offset, Integer limit) { 699 | return this.get("playlists", new String[]{ 700 | "order", "created_at", 701 | "limit", Integer.toString(limit), 702 | "offset", Integer.toString(offset) 703 | }); 704 | } 705 | 706 | /** 707 | * Get last 50 playlists. 708 | * 709 | * @return 710 | */ 711 | public ArrayList getPlaylists() { 712 | return this.getPlaylists(0, 50); 713 | } 714 | 715 | /** 716 | * Get a specific user. 717 | * 718 | * @param contact_id 719 | * @return 720 | */ 721 | public User getUser(Integer contact_id) { 722 | return this.get("users/" + Integer.toString(contact_id)); 723 | } 724 | 725 | /** 726 | * Get last users. 727 | * 728 | * @param limit 729 | * @param offset 730 | * @return 731 | */ 732 | public ArrayList getUsers(Integer offset, Integer limit) { 733 | return this.get("users", new String[]{ 734 | "order", "created_at", 735 | "limit", Integer.toString(limit), 736 | "offset", Integer.toString(offset) 737 | }); 738 | } 739 | 740 | /** 741 | * Get last users. 742 | * 743 | * @return 744 | */ 745 | public ArrayList getUsers() { 746 | return this.getUsers(0, 50); 747 | } 748 | 749 | /** 750 | * Simple user search. 751 | * 752 | * @param username 753 | * @return 754 | */ 755 | public ArrayList findUser(String username) { 756 | return this.get("users", new String[]{ 757 | "q", username 758 | }); 759 | } 760 | 761 | /** 762 | * Get a specific track. 763 | * 764 | * @param track_id 765 | * @return 766 | */ 767 | public Track getTrack(Integer track_id) { 768 | return this.get("tracks/" + Integer.toString(track_id)); 769 | } 770 | 771 | /** 772 | * Get last tracks. 773 | * 774 | * @param offset 775 | * @param limit 776 | * @return 777 | */ 778 | public ArrayList getTracks(Integer offset, Integer limit) { 779 | return this.get("tracks", new String[]{ 780 | "order", "created_at", 781 | "limit", Integer.toString(limit), 782 | "offset", Integer.toString(offset) 783 | }); 784 | } 785 | 786 | /** 787 | * Get last 50 tracks. 788 | * 789 | * @return 790 | */ 791 | public ArrayList getTracks() { 792 | return this.getTracks(0, 50); 793 | } 794 | 795 | /** 796 | * Get tracks from specific group. 797 | * 798 | * @param group_id 799 | * @return 800 | */ 801 | public ArrayList getTracksFromGroup(Integer group_id) { 802 | return this.get("groups/" + Integer.toString(group_id) + "/tracks"); 803 | } 804 | 805 | /** 806 | * Simple track search. 807 | * 808 | * @param title 809 | * @return 810 | */ 811 | public ArrayList findTrack(String title) { 812 | return this.get("tracks", new String[]{ 813 | "q", title 814 | }); 815 | } 816 | 817 | /** 818 | * Get a specific group. 819 | * 820 | * @param id 821 | * @return 822 | */ 823 | public Group getGroup(Integer id) { 824 | return this.get("groups/" + Integer.toString(id)); 825 | } 826 | 827 | /** 828 | * Get last groups. 829 | * 830 | * @param offset 831 | * @param limit 832 | * @return 833 | */ 834 | public ArrayList getGroups(Integer offset, Integer limit) { 835 | return this.get("groups", new String[]{ 836 | "order", "created_at", 837 | "limit", Integer.toString(limit), 838 | "offset", Integer.toString(offset) 839 | }); 840 | } 841 | 842 | /** 843 | * Get last 50 groups. 844 | * 845 | * @return 846 | */ 847 | public ArrayList getGroups() { 848 | return this.getGroups(0, 50); 849 | } 850 | 851 | /** 852 | * Simple user search. 853 | * 854 | * @param name 855 | * @return 856 | */ 857 | public ArrayList findGroup(String name) { 858 | return this.get("groups", new String[]{ 859 | "q", name 860 | }); 861 | } 862 | 863 | /** 864 | * Update your account. 865 | * 866 | * @param user 867 | * @return 868 | */ 869 | public User putMe(User user) { 870 | return this.put("me", user); 871 | } 872 | 873 | /** 874 | * Favor a specific track. 875 | * 876 | * @param track_id 877 | * @return 878 | */ 879 | public Boolean putFavoriteTrack(Integer track_id) { 880 | return this.put("me/favorites/" + Integer.toString(track_id)); 881 | } 882 | 883 | /** 884 | * Post a new track. 885 | * 886 | * @param track 887 | * @return 888 | */ 889 | public Track postTrack(Track track) { 890 | return this.post("tracks", track); 891 | } 892 | 893 | /** 894 | * Post a new comment to a specific track. 895 | * 896 | * @param track_id 897 | * @param comment 898 | * @return 899 | */ 900 | public Comment postCommentToTrack(Integer track_id, Comment comment) { 901 | return this.post("tracks/" + Integer.toString(track_id) + "/comments", comment); 902 | } 903 | 904 | /** 905 | * Delete a specific track. 906 | * 907 | * @param track_id 908 | * @return 909 | */ 910 | public Boolean deleteTrack(Integer track_id) { 911 | return this.delete("tracks/" + Integer.toString(track_id)); 912 | } 913 | 914 | /** 915 | * Remove a specific favorite track. 916 | * 917 | * @param track_id 918 | * @return 919 | */ 920 | public Boolean deleteFavoriteTrack(Integer track_id) { 921 | return this.delete("me/favorites/" + Integer.toString(track_id)); 922 | } 923 | 924 | /** 925 | * Clean JSON string. 926 | * 927 | * @param string 928 | * @return 929 | */ 930 | private String replaceJsonsBlank(String string) { 931 | Pattern pattern = Pattern.compile(":(?: +)?\"\""); 932 | Matcher matcher = pattern.matcher(string); 933 | return matcher.replaceAll(":null"); 934 | } 935 | 936 | } -------------------------------------------------------------------------------- /src/main/java/de/voidplus/soundcloud/Track.java: -------------------------------------------------------------------------------- 1 | package de.voidplus.soundcloud; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import org.apache.http.HttpResponse; 6 | import com.soundcloud.api.Request; 7 | 8 | public class Track { 9 | 10 | private Integer id; 11 | private String created_at; 12 | private Integer user_id; 13 | private User user; 14 | private Integer duration; 15 | private Boolean commentable; 16 | private String state; 17 | private String sharing; 18 | private String tag_list; 19 | private String permalink; 20 | private String description; 21 | private Boolean streamable; 22 | private Boolean downloadable; 23 | private String genre; 24 | private String release; 25 | private String purchase_url; 26 | private Integer label_id; 27 | private String label_name; 28 | private String isrc; 29 | private String video_url; 30 | private String track_type; 31 | private String key_signature; 32 | private String bpm; 33 | private String title; 34 | private Integer release_year; 35 | private Integer release_month; 36 | private Integer release_day; 37 | private String original_format; 38 | private Integer original_content_size; 39 | private String license; 40 | private String uri; 41 | private String permalink_url; 42 | private String artwork_url; 43 | private String waveform_url; 44 | private String stream_url; 45 | private String download_url; 46 | private Integer playback_count; 47 | private Integer download_count; 48 | private Integer favoritings_count; 49 | private Integer comment_count; 50 | private String attachments_uri; 51 | 52 | protected String asset_data; 53 | private transient SoundCloud sc; 54 | 55 | public Track() 56 | { 57 | this.setTagList(""); 58 | } 59 | 60 | public Track(String title, String file) { 61 | this.setTitle(title); 62 | this.setFile(file); 63 | 64 | // Fix: https://github.com/voidplus/soundcloud-java-library/pull/1 65 | this.setTagList(title); 66 | } 67 | 68 | public Integer getId() { 69 | return id; 70 | } 71 | 72 | public void setFile(String file){ 73 | this.asset_data = file; 74 | } 75 | 76 | public String getDescription() { 77 | return description; 78 | } 79 | 80 | public void setDescription(String description) { 81 | this.description = description; 82 | } 83 | 84 | public String getTitle() { 85 | return title; 86 | } 87 | 88 | public void setTitle(String title) { 89 | this.title = title; 90 | } 91 | 92 | public String getCreatedAt() { 93 | return created_at; 94 | } 95 | 96 | public Integer getUserId() { 97 | return user_id; 98 | } 99 | 100 | public User getUser() { 101 | return user; 102 | } 103 | 104 | public Integer getDuration() { 105 | return duration; 106 | } 107 | 108 | public Boolean isCommentable() { 109 | return commentable; 110 | } 111 | 112 | public String getState() { 113 | return state; 114 | } 115 | 116 | public String getSharing() { 117 | return sharing; 118 | } 119 | 120 | public void setTagList(String tag_list) { 121 | this.tag_list = tag_list; 122 | } 123 | 124 | public String getTagList() { 125 | return tag_list; 126 | } 127 | 128 | public String getPermalink() { 129 | return permalink; 130 | } 131 | 132 | public Boolean isStreamable() { 133 | return streamable; 134 | } 135 | 136 | public Boolean isDownloadable() { 137 | return downloadable; 138 | } 139 | 140 | public String getGenre() { 141 | return genre; 142 | } 143 | 144 | public String getRelease() { 145 | return release; 146 | } 147 | 148 | public String getPurchaseUrl() { 149 | return purchase_url; 150 | } 151 | 152 | public Integer getLabelId() { 153 | return label_id; 154 | } 155 | 156 | public String getLabelName() { 157 | return label_name; 158 | } 159 | 160 | public String getIsrc() { 161 | return isrc; 162 | } 163 | 164 | public String getVideoUrl() { 165 | return video_url; 166 | } 167 | 168 | public String getTrackType() { 169 | return track_type; 170 | } 171 | 172 | public String getKeySignature() { 173 | return key_signature; 174 | } 175 | 176 | public String getBpm() { 177 | return bpm; 178 | } 179 | 180 | public Integer getReleaseYear() { 181 | return release_year; 182 | } 183 | 184 | public Integer getReleaseMonth() { 185 | return release_month; 186 | } 187 | 188 | public Integer getReleaseDay() { 189 | return release_day; 190 | } 191 | 192 | public String getOriginalFormat() { 193 | return original_format; 194 | } 195 | 196 | public Integer getOriginalContentSize() { 197 | return original_content_size; 198 | } 199 | 200 | public String getLicense() { 201 | return license; 202 | } 203 | 204 | public String getUri() { 205 | return uri; 206 | } 207 | 208 | public String getPermalinkUrl() { 209 | return permalink_url; 210 | } 211 | 212 | public String getArtworkUrl() { 213 | return artwork_url; 214 | } 215 | 216 | public String getWaveformUrl() { 217 | return waveform_url; 218 | } 219 | 220 | public String getDownloadUrl() { 221 | return download_url; 222 | } 223 | 224 | public Integer getPlaybackCount() { 225 | return playback_count; 226 | } 227 | 228 | public Integer getDownloadCount() { 229 | return download_count; 230 | } 231 | 232 | public Integer getFavoritingsCount() { 233 | return favoritings_count; 234 | } 235 | 236 | public Integer getCommentCount() { 237 | return comment_count; 238 | } 239 | 240 | public String getAttachmentsUri() { 241 | return attachments_uri; 242 | } 243 | 244 | public String getStreamUrl() 245 | { 246 | if(this.streamable!=null && this.stream_url!=null){ 247 | if(this.streamable==true && !this.stream_url.equals("")){ 248 | String stream_url = this.stream_url + "/?consumer_key="+this.sc.app_client_id; 249 | stream_url = stream_url.replace("https://", "http://"); 250 | HttpResponse data = null; 251 | try { 252 | data = this.sc.wrapper.get( Request.to(stream_url) ); 253 | } catch (IOException e) { 254 | e.printStackTrace(); 255 | } 256 | return data.getFirstHeader("Location").getValue().replace("https://", "http://"); 257 | } 258 | } 259 | return null; 260 | } 261 | 262 | public void setSoundCloud(SoundCloud _sc) 263 | { 264 | this.sc = _sc; 265 | } 266 | 267 | @Override 268 | public String toString() { 269 | return "Track [id=" + id + ", created_at=" + created_at + ", user_id=" 270 | + user_id + ", duration=" + duration + ", commentable=" 271 | + commentable + ", state=" + state + ", sharing=" + sharing 272 | + ", tag_list=" + tag_list + ", permalink=" + permalink 273 | + ", streamable=" + streamable 274 | + ", downloadable=" + downloadable + ", genre=" + genre 275 | + ", release=" + release + ", purchase_url=" + purchase_url 276 | + ", label_id=" + label_id + ", label_name=" + label_name 277 | + ", isrc=" + isrc + ", video_url=" + video_url 278 | + ", track_type=" + track_type + ", key_signature=" 279 | + key_signature + ", bpm=" + bpm + ", title=" + title 280 | + ", release_year=" + release_year + ", release_month=" 281 | + release_month + ", release_day=" + release_day 282 | + ", original_format=" + original_format 283 | + ", original_content_size=" + original_content_size 284 | + ", license=" + license + ", uri=" + uri + ", permalink_url=" 285 | + permalink_url + ", artwork_url=" + artwork_url 286 | + ", waveform_url=" + waveform_url + ", user=" + user 287 | + ", stream_url=" + stream_url + ", download_url=" 288 | + download_url + ", playback_count=" + playback_count 289 | + ", download_count=" + download_count + ", favoritings_count=" 290 | + favoritings_count + ", comment_count=" + comment_count 291 | + ", attachments_uri=" + attachments_uri + "]"; 292 | } 293 | 294 | } 295 | -------------------------------------------------------------------------------- /src/main/java/de/voidplus/soundcloud/User.java: -------------------------------------------------------------------------------- 1 | package de.voidplus.soundcloud; 2 | 3 | public class User { 4 | 5 | private Integer id; 6 | private String kind; 7 | private String permalink; 8 | private String username; 9 | private String uri; 10 | private String permalink_url; 11 | private String avatar_url; 12 | private String country; 13 | private String full_name; 14 | private String description; 15 | private String city; 16 | private String discogs_name; 17 | private String myspace_name; 18 | private String website; 19 | private String website_title; 20 | private Boolean online; 21 | private Integer track_count; 22 | private Integer playlist_count; 23 | private String plan; 24 | private Integer public_favorites_count; 25 | private Integer followers_count; 26 | private Integer followings_count; 27 | private Integer private_tracks_count; 28 | private Integer private_playlists_count; 29 | private Boolean primary_email_confirmed; 30 | 31 | public User() 32 | { 33 | } 34 | 35 | public Integer getId() { 36 | return id; 37 | } 38 | 39 | public String getUsername() { 40 | return username; 41 | } 42 | 43 | public void setUsername(String username) { 44 | this.username = username; 45 | } 46 | 47 | public String getCountry() { 48 | return country; 49 | } 50 | 51 | public void setCountry(String country) { 52 | this.country = country; 53 | } 54 | 55 | public String getFullName() { 56 | return full_name; 57 | } 58 | 59 | public String getDescription() { 60 | return description; 61 | } 62 | 63 | public void setDescription(String description) { 64 | this.description = description; 65 | } 66 | 67 | public String getCity() { 68 | return city; 69 | } 70 | 71 | public void setCity(String city) { 72 | this.city = city; 73 | } 74 | 75 | public String getDiscogsName() { 76 | return discogs_name; 77 | } 78 | 79 | public void setDiscogsName(String discogs_name) { 80 | this.discogs_name = discogs_name; 81 | } 82 | 83 | public String getMyspaceName() { 84 | return myspace_name; 85 | } 86 | 87 | public void setMyspaceName(String myspace_name) { 88 | this.myspace_name = myspace_name; 89 | } 90 | 91 | public String getWebsite() { 92 | return website; 93 | } 94 | 95 | public void setWebsite(String website) { 96 | this.website = website; 97 | } 98 | 99 | public String getWebsiteTitle() { 100 | return website_title; 101 | } 102 | 103 | public void setWebsiteTitle(String website_title) { 104 | this.website_title = website_title; 105 | } 106 | 107 | public String getKind() { 108 | return kind; 109 | } 110 | 111 | public String getPermalink() { 112 | return permalink; 113 | } 114 | 115 | public String getUri() { 116 | return uri; 117 | } 118 | 119 | public String getPermalinkUrl() { 120 | return permalink_url; 121 | } 122 | 123 | public String getAvatarUrl() { 124 | return avatar_url; 125 | } 126 | 127 | public Boolean isOnline() { 128 | return online; 129 | } 130 | 131 | public Integer getTrackCount() { 132 | return track_count; 133 | } 134 | 135 | public Integer getPlaylistCount() { 136 | return playlist_count; 137 | } 138 | 139 | public String getPlan() { 140 | return plan; 141 | } 142 | 143 | public Integer getPublicFavoritesCount() { 144 | return public_favorites_count; 145 | } 146 | 147 | public Integer getFollowersCount() { 148 | return followers_count; 149 | } 150 | 151 | public Integer getFollowingsCount() { 152 | return followings_count; 153 | } 154 | 155 | public Integer getPrivateTracksCount() { 156 | return private_tracks_count; 157 | } 158 | 159 | public Integer getPrivatePlaylistsCount() { 160 | return private_playlists_count; 161 | } 162 | 163 | public Boolean getPrimaryEmailConfirmed() { 164 | return primary_email_confirmed; 165 | } 166 | 167 | @Override 168 | public String toString() { 169 | return "User [id=" + id + ", kind=" + kind + ", permalink=" + permalink 170 | + ", username=" + username + ", uri=" + uri 171 | + ", permalink_url=" + permalink_url + ", avatar_url=" 172 | + avatar_url + ", country=" + country + ", full_name=" 173 | + full_name + ", description=" + description + ", city=" + city 174 | + ", discogs_name=" + discogs_name + ", myspace_name=" 175 | + myspace_name + ", website=" + website + ", website_title=" 176 | + website_title + ", online=" + online + ", track_count=" 177 | + track_count + ", playlist_count=" + playlist_count 178 | + ", plan=" + plan + ", public_favorites_count=" 179 | + public_favorites_count + ", followers_count=" 180 | + followers_count + ", followings_count=" + followings_count 181 | + ", private_tracks_count=" + private_tracks_count 182 | + ", private_playlists_count=" + private_playlists_count 183 | + ", primary_email_confirmed=" + primary_email_confirmed + "]"; 184 | } 185 | 186 | } -------------------------------------------------------------------------------- /src/test/java/de/voidplus/soundcloud/SoundCloudTest.java: -------------------------------------------------------------------------------- 1 | package de.voidplus.soundcloud; 2 | 3 | import org.junit.BeforeClass; 4 | import org.junit.Test; 5 | 6 | import java.io.IOException; 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.lang.reflect.Method; 9 | import java.net.HttpURLConnection; 10 | import java.net.URL; 11 | import java.util.ArrayList; 12 | 13 | import static org.junit.Assert.*; 14 | import static org.junit.Assume.assumeTrue; 15 | import static org.mockito.Mockito.mock; 16 | import static org.mockito.Mockito.when; 17 | 18 | public class SoundCloudTest { 19 | 20 | public static String apiHost = "https://api.soundcloud.com"; 21 | 22 | public static SoundCloud sc; 23 | public static boolean login; 24 | 25 | // reflection 26 | public static Method methodFilterApiStr, methodDefineApiType; 27 | 28 | // mock class 29 | public static SoundCloud mockedSc; 30 | 31 | @BeforeClass 32 | public static void setup() throws NoSuchMethodException { 33 | sc = new SoundCloud(System.getenv("APP_ID"), System.getenv("APP_SECRET")); 34 | login = sc.login(System.getenv("LOGIN_MAIL"), System.getenv("LOGIN_PASS")); 35 | 36 | // mock class for offline tests 37 | mockedSc = mock(SoundCloud.class); 38 | User mockedUser = new User(); 39 | mockedUser.setUsername("Darius"); 40 | when(mockedSc.getMe()).thenReturn(mockedUser); 41 | 42 | // test different kinds of api strings 43 | methodFilterApiStr = sc.getClass().getDeclaredMethod("filterApiString", String.class); 44 | methodFilterApiStr.setAccessible(true); 45 | 46 | // test different kinds of rest types 47 | methodDefineApiType = sc.getClass().getDeclaredMethod("defineApiType", String.class); 48 | methodDefineApiType.setAccessible(true); 49 | } 50 | 51 | /** 52 | * Test if specific API is reachable. 53 | * 54 | * @param url Without slash at the beginning! 55 | * @return 56 | * @throws IOException 57 | */ 58 | public static boolean isReachable(String url) { 59 | url = apiHost + url; 60 | try { 61 | URL u = new URL(url); 62 | HttpURLConnection huc = (HttpURLConnection) u.openConnection(); 63 | huc.setRequestMethod("GET"); 64 | huc.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)"); 65 | huc.connect(); 66 | return huc.getResponseCode() == 200 || huc.getResponseCode() == 401; 67 | } catch (Exception e) { 68 | // e.printStackTrace(); 69 | System.err.println("Specific API URL (" + url + ") isn't reachable."); 70 | return false; 71 | } 72 | } 73 | 74 | // -------------------------------------------- 75 | // API 76 | 77 | // GET 78 | 79 | @Test 80 | public void testApiLogin() { 81 | assumeTrue(isReachable("/")); 82 | 83 | assertTrue(login); 84 | } 85 | 86 | @Test 87 | public void testApiGetMe() { 88 | assumeTrue(isReachable("/me")); 89 | assumeTrue(login); 90 | 91 | User a = sc.getMe(); 92 | assertNotNull(a.getId()); 93 | } 94 | 95 | @Test 96 | public void testApiGetMeEquality() { 97 | assumeTrue(isReachable("/me")); 98 | assumeTrue(login); 99 | 100 | User a = sc.getMe(); 101 | User b = sc.get("/me"); 102 | assertEquals(a.getId(), b.getId()); 103 | } 104 | 105 | @Test 106 | public void testApiGetWithArgs() { 107 | assumeTrue(isReachable("/tracks")); 108 | assumeTrue(login); 109 | 110 | ArrayList tracks = sc.get("tracks", new String[]{ 111 | "order", "created_at", 112 | "filter", "streamable", 113 | "limit", "10" 114 | }); 115 | assertTrue(tracks.size() > 0 && tracks.get(0).isStreamable()); 116 | } 117 | 118 | @Test 119 | public void testFindTrackShortcut() { 120 | assumeTrue(isReachable("/tracks")); 121 | assumeTrue(login); 122 | 123 | ArrayList tracks = sc.findTrack("I love you"); 124 | assertTrue(tracks.size() > 0); 125 | } 126 | 127 | @Test 128 | public void testFindUserShortCut() { 129 | assumeTrue(isReachable("/users")); 130 | assumeTrue(login); 131 | 132 | ArrayList users = sc.findUser("Björk"); 133 | assertTrue(users.size() > 0); 134 | } 135 | 136 | // PUT 137 | 138 | @Test 139 | public void testApiPutMe() { 140 | assumeTrue(isReachable("/users")); 141 | assumeTrue(login); 142 | 143 | User me = sc.getMe(); 144 | String city = me.getCity(); 145 | city = city == null ? "Stuttgart" : city.equals("Stuttgart") ? "Berlin" : "Stuttgart"; 146 | me.setCity(city); 147 | sc.putMe(me); 148 | assertTrue(me.getCity().equals(city)); 149 | } 150 | 151 | 152 | // -------------------------------------------- 153 | // Data-Preprocessing 154 | 155 | @Test 156 | public void testPreFilterApiStr1() throws InvocationTargetException, IllegalAccessException { 157 | String api = "/me"; 158 | String str = (String) methodFilterApiStr.invoke(sc, api); 159 | assertEquals("/me.json", str); 160 | } 161 | 162 | @Test 163 | public void testPreFilterApiStr2() throws InvocationTargetException, IllegalAccessException { 164 | String api = "me/"; 165 | String str = (String) methodFilterApiStr.invoke(sc, api); 166 | assertEquals("/me.json", str); 167 | } 168 | 169 | @Test 170 | public void testPreFilterApiStr3() throws InvocationTargetException, IllegalAccessException { 171 | String api = "me.format"; 172 | String str = (String) methodFilterApiStr.invoke(sc, api); 173 | assertEquals("/me.json", str); 174 | } 175 | 176 | @Test 177 | public void testPreFilterApiStr4() throws InvocationTargetException, IllegalAccessException { 178 | String api = "/me.xml"; 179 | String str = (String) methodFilterApiStr.invoke(sc, api); 180 | assertEquals("/me.json", str); 181 | } 182 | 183 | @Test 184 | public void testPreDefineApiType() throws InvocationTargetException, IllegalAccessException { 185 | String api = "/me.json"; 186 | SoundCloud.Type type = (SoundCloud.Type) methodDefineApiType.invoke(sc, api); 187 | assertTrue(SoundCloud.Type.USER == type); 188 | } 189 | 190 | // -------------------------------------------- 191 | // Mock (offline) 192 | 193 | @Test 194 | public void testMockApiGetMe() { 195 | User a = mockedSc.getMe(); 196 | assertEquals(a.getUsername(), "Darius"); 197 | } 198 | 199 | } 200 | -------------------------------------------------------------------------------- /target/soundcloud-0.2.1-jar-with-dependencies.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nok/soundcloud-java-library/ce05aac18ab5fb2a420e32a81986b67da50885a5/target/soundcloud-0.2.1-jar-with-dependencies.jar -------------------------------------------------------------------------------- /target/soundcloud-0.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nok/soundcloud-java-library/ce05aac18ab5fb2a420e32a81986b67da50885a5/target/soundcloud-0.2.1.jar --------------------------------------------------------------------------------