// GetIndexes is used in Subsonic to return an alphabetical index of artists and IDs func GetIndexes(res http.ResponseWriter, req *http.Request) { // Retrieve render r := context.Get(req, api.CtxRender).(*render.Render) // Create a new response container, build indexes container c := newContainer() c.Indexes = &IndexesContainer{ LastModified: common.ScanTime(), } // Fetch list of all artists, ordered alphabetically artists, err := data.DB.AllArtistsByTitle() if err != nil { log.Println(err) r.XML(res, 200, ErrGeneric) return } // Use a set to track indexes which already exist indexSet := set.New() // Iterate all artists and begin building indexes indexes := make([]Index, 0) // Use a counter which is incremented each time a new index is added, in order to // add artists at the right index i := -1 for _, a := range artists { // Get the initial character of the artist title char := string(a.Title[0]) // Create the index if it doesn't already exist, increment counter so new artists // slot into that index if indexSet.Add(char) { indexes = append(indexes, Index{Name: char}) i++ } // Add this folder to the index at the current position indexes[i].Artists = append(indexes[i].Artists, Artist{ Name: a.Title, // Since Subsonic and wavepipe have different data models, we get around // the ID restriction by adding a prefix describing what this actually is ID: "artist_" + strconv.Itoa(a.ID), }) } // Add indexes, write response c.Indexes.Indexes = indexes r.XML(res, 200, c) }
// GetDatabaseMetrics returns a variety of metrics about the wavepipe database, including // total numbers of specific objects, and the time when the database was last updated func GetDatabaseMetrics() (*DatabaseMetrics, error) { // Fetch total artists artists, err := data.DB.CountArtists() if err != nil { return nil, err } // Fetch total albums albums, err := data.DB.CountAlbums() if err != nil { return nil, err } // Fetch total songs songs, err := data.DB.CountSongs() if err != nil { return nil, err } // Fetch total folders folders, err := data.DB.CountFolders() if err != nil { return nil, err } // Fetch total art art, err := data.DB.CountArt() if err != nil { return nil, err } // Combine all metrics return &DatabaseMetrics{ Updated: common.ScanTime(), Artists: artists, Albums: albums, Songs: songs, Art: art, Folders: folders, }, nil }
// GetStatus returns the current server status, and optionally, server metrics, with // an HTTP status and JSON. func GetStatus(w http.ResponseWriter, r *http.Request) { // Retrieve render ren := context.Get(r, CtxRender).(*render.Render) // Output struct for songs request out := StatusResponse{} // Check API version if version, ok := mux.Vars(r)["version"]; ok { // Check if this API call is supported in the advertised version if !apiVersionSet.Has(version) { ren.JSON(w, 400, errRes(400, "unsupported API version: "+version)) return } } // Retrieve current server status out.Status = common.ServerStatus() // If requested, fetch additional metrics (not added by default due to full table scans in database) if metricTypes := r.URL.Query().Get("metrics"); metricTypes != "" { // Begin building metrics outMetrics := &metrics.Metrics{} // Constants to check for various metric types const ( mAll = "all" mDatabase = "database" mNetwork = "network" ) // Set of valid metric types validSet := set.New(mAll, mDatabase, mNetwork) // Check for comma-separated list of metric types metricSet := set.New() for _, m := range strings.Split(metricTypes, ",") { // Add valid types to set if validSet.Has(m) { metricSet.Add(m) } } // If requested, get metrics about the database if metricSet.Has(mAll) || metricSet.Has(mDatabase) { // Check for cached metrics, and make sure they are up to date if databaseMetricsCache != nil && common.ScanTime() <= cacheTime { outMetrics.Database = databaseMetricsCache } else { // Fetch new metrics dbMetrics, err := metrics.GetDatabaseMetrics() if err != nil { log.Println(err) ren.JSON(w, 500, serverErr) return } outMetrics.Database = dbMetrics // Cache metrics and update time databaseMetricsCache = dbMetrics cacheTime = time.Now().Unix() } } // If requested, get metrics about the network if metricSet.Has(mAll) || metricSet.Has(mNetwork) { outMetrics.Network = &metrics.NetworkMetrics{ RXBytes: metrics.RXBytes(), TXBytes: metrics.TXBytes(), } } // Return metrics out.Metrics = outMetrics } // HTTP 200 OK with JSON out.Error = nil ren.JSON(w, 200, out) return }