<commit_before>package gosubsonic

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
)

// Constants to pass with each API request
const (
	CLIENT     = "gosubsonic-0.1"
	APIVERSION = "1.8.0"
)

// Subsonic client required fields
type SubsonicClient struct {
	Host     string
	Port     int
	Username string
	Password string
}

// Generate a URL for an API call using given parameters and method
func (s SubsonicClient) makeURL(method string) string {
	return fmt.Sprintf("http://%s:%d/rest/%s.view?u=%s&p=%s&c=%s&v=%s&f=json",
		s.Host, s.Port, method, s.Username, s.Password, CLIENT, APIVERSION)
}

// Fetch a list of all artists known to Subsonic
func (s SubsonicClient) FetchArtists() ([]Artist, error) {
	// List of artists to return
	artists := make([]Artist, 0)

	// Request a list of artists from API
	res, err := http.Get(s.makeURL("getArtists"))
	if err != nil {
		return artists, errors.New("HTTP request 'getArtists' failed")
	}

	// Read the entire response body, and defer it to be closed
	body, err := ioutil.ReadAll(res.Body)
	defer res.Body.Close()

	// Unmarshal response JSON from API container
	var subRes ApiContainer
	json.Unmarshal(body, &subRes)

	// Check for any errors in response object
	if subRes.Response.Error != (ApiError{}) {
		// Report error and code
		return artists, errors.New(fmt.Sprintf("%d: %s", subRes.Response.Error.Code, subRes.Response.Error.Message))
	}

	// Iterate all indices to get artist lists inside
	for _, i := range subRes.Response.Artists.Index {
		// Iterate all artists and append to list
		for _, a := range i.Artist {
			artists = append(artists[:], a)
		}
	}

	// Return list of artists
	return artists, nil
}

// Fetch artist by ID from Subsonic
func (s SubsonicClient) GetArtist(id int) (Artist, error) {
	// Request artist from API, by ID
	res, err := http.Get(s.makeURL("getArtist") + "&id=" + strconv.FormatInt(int64(id), 10))
	if err != nil {
		return Artist{}, errors.New("HTTP request 'getArtist' failed")
	}

	// Read the entire response body, and defer it to be closed
	body, err := ioutil.ReadAll(res.Body)
	defer res.Body.Close()

	// Unmarshal response JSON from API container
	var subRes ApiContainer
	json.Unmarshal(body, &subRes)

	// Check for any errors in response object
	if subRes.Response.Error != (ApiError{}) {
		// Report error and code
		return Artist{}, errors.New(fmt.Sprintf("%d: %s", subRes.Response.Error.Code, subRes.Response.Error.Message))
	}

	// Return artist
	return subRes.Response.Artist, nil
}<commit_msg>Refactor and reduce redundancy in subsonicClient<commit_after>package gosubsonic

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
)

// Constants to pass with each API request
const (
	CLIENT     = "gosubsonic-0.1"
	APIVERSION = "1.8.0"
)

// Subsonic client required fields
type SubsonicClient struct {
	Host     string
	Port     int
	Username string
	Password string
}

// Generate a URL for an API call using given parameters and method
func (s SubsonicClient) makeURL(method string) string {
	return fmt.Sprintf("http://%s:%d/rest/%s.view?u=%s&p=%s&c=%s&v=%s&f=json",
		s.Host, s.Port, method, s.Username, s.Password, CLIENT, APIVERSION)
}

// Fetch JSON from specified URL and parse into ApiContainer
func fetchJSON(url string) (ApiContainer, error) {
	// Make an API request
	res, err := http.Get(url)
	if err != nil {
		return ApiContainer{}, errors.New("HTTP request failed: " + url)
	}

	// Read the entire response body, and defer it to be closed
	body, err := ioutil.ReadAll(res.Body)
	defer res.Body.Close()

	// Unmarshal response JSON from API container
	var subRes ApiContainer
	json.Unmarshal(body, &subRes)

	// Check for any errors in response object
	if subRes.Response.Error != (ApiError{}) {
		// Report error and code
		return ApiContainer{}, errors.New(fmt.Sprintf("%d: %s", subRes.Response.Error.Code, subRes.Response.Error.Message))
	}

	// Return the response container
	return subRes, nil
}

// Fetch a list of all artists known to Subsonic
func (s SubsonicClient) FetchArtists() ([]Artist, error) {
	// List of artists to return
	artists := make([]Artist, 0)

	// Query for list of all artists
	res, err := fetchJSON(s.makeURL("getArtists"))
	if err != nil {
		return artists, err
	}

	// Iterate all indices to get artist lists inside
	for _, i := range res.Response.Artists.Index {
		// Iterate all artists and append to list
		for _, a := range i.Artist {
			artists = append(artists[:], a)
		}
	}

	// Return list of artists
	return artists, nil
}

// Fetch artist by ID from Subsonic
func (s SubsonicClient) GetArtist(id int) (Artist, error) {
	// Request artist from API, by ID
	res, err := fetchJSON(s.makeURL("getArtist") + "&id=" + strconv.FormatInt(int64(id), 10))
	if err != nil {
		return Artist{}, err
	}

	// Return artist
	return res.Response.Artist, nil
}
{'fraction_non_alphanumeric': 0.12767269736842105, 'fraction_numerical': 0.004111842105263158, 'mean_word_length': 3.727891156462585, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2975800', 'n_tokens_mistral': 1697, 'n_tokens_neox': 1649, 'n_words': 530}