they dropped the need for an API key when they went from 1.0 to 2.0
For access to image URLs it still requires a "consumer" key (as you mention). Whatever they call it, it's still a key I need in order to access the API, which has to be kept secret. Looks like an API key to me! Keeping a key secret is not an option for AAD, so I'm not going to write a script that requires it. I do take your point that users with registered discogs accounts could generate their own keys and then supply them in some sort of config file, or by editing the script, but that's not really a model I'm interested in putting much work into.
Like Shakespeare said, "an API key by any other name..." 
If anyone else wants to write a discogs-api script based on this principle, I'd be happy to include it in the list of scripts, though,
Tempting, but might be a bit beyond my meager skills.
I did, however, edit Discogs.boo to be better at finding various-artist compilations. Discogs considers the artist for various-artist compilations to be "Various" and I personally index my collection as "Various Artists" (and others truncate it to "VA"). So this (crude) hack will feed Discogs "various" even if the "actual" artist per the file tags is "Various Artists" or "VA".
The edits are on lines 25-29; I could probably have just done an OR but, eh, why write two lines when you can write four. 
# refs: System.Web.Extensions
import System
import System.Text.RegularExpressions
import System.Web.Script.Serialization
import AlbumArtDownloader.Scripts
import util
class Discogs(AlbumArtDownloader.Scripts.IScript):
def constructor():
// Discogs requires TLS 1.1 or greater
Tls12 = Enum.ToObject(typeof(System.Net.SecurityProtocolType), 3072);
Tls11 = Enum.ToObject(typeof(System.Net.SecurityProtocolType), 768);
System.Net.ServicePointManager.SecurityProtocol = Tls12 | Tls11 | System.Net.SecurityProtocolType.Tls
Name as string:
get: return "Discogs"
Author as string:
get: return "Alex Vallat"
Version as string:
get: return "0.27"
def Search(artist as string, album as string, results as IScriptResults):
//artist = StripCharacters("&.'\";:?!", artist)
//album = StripCharacters("&.'\";:?!", album)
//Discogs lists Various Artists compilations under "Various", many collections term these "Various Artists" or "VA"
if (artist = "Various Artists"):
artist="Various"
if (artist = "VA"):
artist="Various"
json = JavaScriptSerializer()
resultsInfoJson = GetDiscogsPage("https://www.discogs.com/search/ac?searchType=release&q=" + EncodeUrl("\"${artist}\" \"${album}\""))
resultsInfo = json.Deserialize[of (Result)](resultsInfoJson)
results.EstimatedCount = resultsInfo.Length;
for result in resultsInfo:
// Get the release info from api
title = result.GetString(result.artist) + " - " + result.GetString(result.title);
url = result.GetString(result.uri);
//id = url.Substring(url.LastIndexOf('/'));
releasePage = GetDiscogsPage("https://www.discogs.com" + url)
releasePageImagesMatches = Regex("\"Image:{[^{]+}\":(?<json>{.+?}})", RegexOptions.IgnoreCase | RegexOptions.Singleline).Matches(releasePage)
for match as Match in releasePageImagesMatches:
imageInfo = json.Deserialize[of ImageInfo](match.Groups["json"].Value)
if (imageInfo.fullsize != null and imageInfo.thumbnail != null):
fullInfo = json.Deserialize[of ImageRef](imageInfo.fullsize.__ref.Substring(10))
thumbInfo = json.Deserialize[of ImageRef](imageInfo.thumbnail.__ref.Substring(10))
results.Add(thumbInfo.sourceUrl, title, "https://www.discogs.com" + url + "/image/" + imageInfo.id, -1, -1, fullInfo.sourceUrl, CoverType.Unknown)
def RetrieveFullSizeImage(fullSizeCallbackParameter):
return GetPageStream(fullSizeCallbackParameter, null, true);
def GetDiscogsPage(url) as string:
request = System.Net.HttpWebRequest.Create(url) as System.Net.HttpWebRequest
request.Accept = "*/*"
request.UserAgent = "Mozilla/5.0 (AAD on " + System.Environment.MachineName + ")"
try:
response = request.GetResponse()
except ex as WebException:
exResponse = ex.Response as System.Net.HttpWebResponse
if (exResponse != null and exResponse.StatusCode == 308):
return GetDiscogsPage(exResponse.GetResponseHeader("Location"))
raise
stream = response.GetResponseStream()
try:
return GetPage(stream)
ensure:
stream.Close()
class Result:
public artist as object
public title as object
public uri as object
def GetString(value):
result = value as string;
if result is null:
result = (value as (object))[0] as string;
return result;
class ImageInfo:
public id as string
public thumbnail as ImageRefJson
public fullsize as ImageRefJson
class ImageRefJson:
public __ref as string
class ImageRef:
public sourceUrl as string