Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 97bfbf60ac
Fetching contributors…

Cannot retrieve contributors at this time

file 119 lines (101 sloc) 3.58 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
querystring = require 'querystring'
request = require 'request'
zlib = require 'zlib'

# This is the entry point.
#
# Takes an optional format parameter, defaulting to 'json'. If 'xml' consumer is expected to take care of parsing
#
# client = discogs("xml")
exports = module.exports = (format) ->
  # Return a proper url with optional format
  getUrl = (url) ->
    sep = if "?" in url then "&" else "?"
    url = "http://api.discogs.com/#{url}" if url.substr(0, 7) isnt 'http://'

    url += "#{sep}f=#{format}" if format
    url

  # Make a request
  discogsRequest = (url, next) ->
    parseResponse = (err, res, body) ->
      return next err if err
      if ~res.headers['content-type']?.indexOf('json') or not format
        try
          body = JSON.parse body
        catch e
          err = e
          body = null
        next err, body

    request
      uri: getUrl url
      headers: {'accept-encoding': 'gzip'}
      encoding: null
      (error, res, body) ->
        if not error and 200 <= res.statusCode < 400
          if ~res.headers['content-encoding']?.indexOf 'gzip'
            zlib.gunzip body, (err, body) ->
              parseResponse err, res, body
          else
            parseResponse error, res, body
        else
          next error

  responseHandler = (type, next) ->
    (err, res) ->
      return next(err, res) if err or res not instanceof Object or type not of res?.resp
      next(null, res.resp[type])

  # API

  # Use this if you have a discogs url
  get: (url, next) ->
    discogsRequest url, next

  # Get a release
  master: (id, next) ->
    discogsRequest 'master/' + id,
      responseHandler('master', next)

  # Get a release
  release: (id, next) ->
    discogsRequest 'release/' + id,
      responseHandler('release', next)

  # Get an artist
  artist: (name, next) ->
    discogsRequest 'artist/' + name,
      responseHandler('artist', next)

  # Get a label
  label: (name, next) ->
    discogsRequest 'label/' + name,
      responseHandler('label', next)

  # Search for something
  # Valid types:
  # `all`, `artists`, `labels`, `releases`, `needsvote`, `catno`, `forsale`
  search: (query, type, next) ->
    if type instanceof Function
      next = type
      type = 'all'
    discogsRequest 'search?' + querystring.stringify(type: type, q: query),
      responseHandler('search', next)

  # Do a search and try to find the master or main release in all results.
  # Uses 2 or 3 requests per lookup, to find the best result.
  lookup: (query, next) ->
    @search query, "releases", (err, res) =>
      return next err if err

      results = res?.searchresults?.results
      return next() unless results

      masters = (result for result in results when result.type is "master")
      # Did we find masters already?
      results = masters if masters.length

      matches = (result for result in results when result.title.toLowerCase() is query.toLowerCase())
      # Take only the best results
      results = matches if matches.length

      release = results[0]
      id = release.uri.split("/").pop()

      @[release.type] id, (err, res) =>
        if "master_id" of res
          # Did we find a master now?
          @master res.master_id, (err, master) =>
            if "main_release" of master
              @release master.main_release, next
            else
              next null, master
        else if "main_release" of res
          # Or maybe a main release?
          @release res.main_release, next
        else
          # This is the best we can do
          next null, res
Something went wrong with that request. Please try again.