Last tutorial, we covered how to connect to a user's Soundcloud account with OAuth, now we'll take a look at how to upload and manage sounds on Soundcloud with Go.

For this tutorial, be sure to import all of the following:

import (
        "bytes"
	"encoding/json"
	"github.com/rl/stune/appError"
	"io"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

First, we'll upload a sound to Soundcloud. We define the path to our track, take the access token we acquired from the other tutorial and define attributes for our song, I only defined two, but you can set a whole bunch of other things. Remember to wrap them in track[].

path := "path/to/your/track.mp3"
params := map[string]string{
	"oauth_token":    YOUR_ACCESS_TOKEN,
	"track[title]":   "Test Track",
	"track[sharing]": "public",
}

Next, we will open the filepath, and close the file later to prevent memory leaks.

file, err := os.Open(path)
if err != nil {
	return err
}
defer file.Close()

For attaching files and parameters, we will create a form and a buffer to feed the form into.

body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
// Create a field to attach the sound file to.
part, err := writer.CreateFormFile("track[asset_data]", filepath.Base(path))
	if err != nil {
		return nil, &appError.Err{err, "Unable to attach file to form", 500}
	}
// Attach the sound file to the field.
_, err = io.Copy(part, file)

Now that we've attached the file to our form, the rest is easy, iterate through the rest of our *params* and add them to the form.

for key, val := range params {
		err := writer.WriteField(key, val)
		if err != nil {
			return err
		}
	}
// Close the writer because we're done adding things to the form.
err = writer.Close()
if err != nil {
	return err
}

Finally, we just have to send the request and handle the response.

req, err := http.NewRequest("POST", "https://api.soundcloud.com/tracks.json", body)
if err != nil {
	return err
}
req.Header.Set("Content-Type", writer.FormDataContentType())
// Send the request
resp, err := c.Client.Do(req)
if err != nil {
	return err
}
// Create a map with the structure of: key string: value interface
var content map[string]interface{}
// Finally decode the response JSON into content
json.NewDecoder(resp.Body).Decode(&content)
return nil

Now we are going to manage our Soundcloud sounds. This is a GET request since it's publicly available info.

// Convert our string into a *url.URL
u, err := url.Parse("https://api.soundcloud.com/me/tracks.json")
if err != nil {
	return err
}
// Set our parameter to be able to access this
q := u.Query()
q.Set("oauth_token", c.Token.AccessToken)
u.RawQuery = q.Encode()
// Make the request with the method, GET
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
	return err
}
resp, err := c.Client.Do(req)
if err != nil {
	return err
}
// I made this struct inline, but you can instantiate it separately, you may also add more properties to it, but for this demo, I just have Title.
var content []struct{ Title string }
err = json.NewDecoder(resp.Body).Decode(&content)
if err != nil {
	return err
}

Hope you enjoyed the tutorial!

*For part 1 of this series, go to: http://blog.rjdlee.com/beginning-go-and-soundcloud