Skip to content

Instantly share code, notes, and snippets.

@rornor
Last active September 26, 2022 06:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rornor/5498e3a1fce1cce02b59 to your computer and use it in GitHub Desktop.
Save rornor/5498e3a1fce1cce02b59 to your computer and use it in GitHub Desktop.
Uses Google, Bing and Amazon search engines to simplify album cover search
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.cdnjs.com/ajax/libs/json2/20121008/json2.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/dojo.js" data-dojo-config="parseOnLoad:true"></script>
<script>
dojo.require("dojo.parser");
dojo.require("dojox.image.LightboxNano");
</script>
<HTA:APPLICATION
APPLICATIONNAME="Album cover search"
ID="CoverSearch"
VERSION="0.2"
INNERBORDER="no"
BORDER="thin"
SINGLEINSTANCE="no"
NAVIGABLE="no"
MAXIMIZEBUTTON="no"
MINIMIZEBUTTON="yes"
CONTEXTMENU="no"
SELECTION ="no"
SCROLL="no"
ICON="icon.ico"
/>
<style type="text/css">
body { background-color: #fff; margin: 0; border: 0; padding: 0; }
table { border-spacing: 10px; }
div { height: 350px; padding: 0; }
div.google { float: left; width: 600px; background-color: #4285F4; }
div#amazon_l, div#amazon_r { width: 300px; float: right; background-color: #fff; }
div#fanart { width: 300px; float: right; background-color: #C2454B; }
div#bing { width: 300px; float: left; background-color: #FFB900; }
div#bing_opt { width: 300px; display: none; background-color: #FFB900; }
div#nav { position: absolute; top: 12px; left: 550px; width: 100px; height: 18px; }
td { display: block; max-width: 154px; min-height: 20px; font: menu; padding-left: 12px; }
td.split {padding-left: 26px; }
td.header { height: 35px; }
td.header>img { padding-right: 10px; border: 0; }
span { float: left; font: menu; font-size: 8pt; color: #333; border: 0; }
span.button { width: 16px; height: 16px; margin: 0 4px; }
span.favicon { width: 16px; height: 16px; margin: 0 4px; }
span#default { background:url('http://dl.dropboxusercontent.com/u/30782742/img/sprites.png') 0px 0px; }
span#wide { background:url('http://dl.dropboxusercontent.com/u/30782742/img/sprites.png') -16px 0px; }
span#save { float: right; background:url('http://dl.dropboxusercontent.com/u/30782742/img/sprites.png') -32px 0px; }
span#google { background:url('http://dl.dropboxusercontent.com/u/30782742/img/sprites.png') -0px -32px; }
span#bing { background:url('http://dl.dropboxusercontent.com/u/30782742/img/sprites.png') -16px -32px; }
span#amazon { background:url('http://dl.dropboxusercontent.com/u/30782742/img/sprites.png') -32px -32px; }
span#fanart { background:url('http://dl.dropboxusercontent.com/u/30782742/img/sprites.png') -48px -32px; }
span#default:hover { background:url('http://dl.dropboxusercontent.com/u/30782742/img/sprites.png') 0px -16px; }
span#wide:hover { background:url('http://dl.dropboxusercontent.com/u/30782742/img/sprites.png') -16px -16px; }
span#save:hover { background:url('http://dl.dropboxusercontent.com/u/30782742/img/sprites.png') -32px -16px; }
span.message { display: block; float: none; border: 1px solid red; color: white; padding: 10px; margin: 100px auto; width: 200px; }
span.button:hover { cursor: hand; }
img.thumb { width: 120px; height: 120px; }
a { text-decoration: none; color: #000; padding: 2px; }
a:hover { color: #EB008B; border: 0; }
a img { border: 2px solid #333; border-radius: 10px; }
a img:hover { border: 2px solid #00ACEE; }
</style>
</head>
<script language="javascript">
function Google(kwd)
{
var jsonData = Request("http://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=" + encodeURI(kwd) + "&imgsz=large&rsz=8")
try
{
var result = JSON.parse(jsonData);
var gTable = "<div id='google' class='google'><table><tr><td class='header'><span class='favicon' id='google'></span><a href='https://www.google.com/search?q=" + kwd + "&tbm=isch' target='_blank' title='Open in browser'>more...</a></td></tr><tr>\r\n";
for (i in result.responseData.results)
{
var res = result.responseData.results[i];
gTable += (i!=0 && i%4==0) ? "</tr><tr>" : "";
split = (i==2 || i==6) ? " class='split'" : "";
gTable += "<td" + split + "><a dojoType='dojox.image.LightboxNano' title='Preview' href='" + res.url + "'><img class='thumb' src='" +
res.tbUrl + "'></a><span class='button' id='save' title='Save...' onclick='Download(\"" + res.url + "\")'>&nbsp;</span>" +
"<span>" + res.width + " x " + res.height + "</span></td>\r\n";
}
return gTable + "</table></div>";
}
catch (e)
{
return "<div id='google' class='google'><span class='message'>" + e.name + ": " + e.message + "</span></div>";
}
}
function swapNodes(node1, node2)
{
node1.parentNode.replaceChild(node1, node2);
node1.parentNode.insertBefore(node2, node1);
}
function prependNode(node1, node2) { node1.parentNode.insertBefore(node2, node1); }
function uenc(s) { return encodeURIComponent(s); }
</script>
<script language="vbscript">
default_folder = ""
default_filename = ""
arg = Split(CoverSearch.commandLine, Chr(34))
If Ubound(arg) > 4 Then
album = arg(3)
artist = arg(5)
kwd = album & " " & artist
Else
msgbox "Example usage:" & vbCrLf & vbCrLf & "cover_search.hta ""%album%"" ""%artist%"" [""$directory_path(%path%)""]", 64, "Information"
window.close
End If
Function Bing(kwd)
With CreateObject("MSXML2.DOMDocument.6.0")
.async = False
.validateOnParse = False
.resolveExternals = True
.setProperty "ProhibitDTD", False
url = "http://www.bing.com/images/search?q=" & uenc(kwd) & "&view=large"
If .load(url) Then
.setProperty "SelectionLanguage", "XPath"
.setProperty "SelectionNamespaces", "xmlns:xhtml='http://www.w3.org/1999/xhtml'"
bmTable = "<div id='bing_main' class='bingMain'><div id='bing'><table><tr><td class='header'><span class='favicon' id='bing'></span><a href='http://www.bing.com/images/search?q=" & kwd & "' target='_blank' title='Open in browser'>more...</a></td></tr><tr>" & vbCrLf
For Each elem In .selectNodes("//xhtml:a[@m]")
For Each m In Split(elem.getAttribute("m"), """,")
mm = Split(m, ":", 2)
If mm(0) = "imgurl" Then imgurl = Replace(mm(1), """", "")
Next
If Not c = 0 Then
If c Mod 8 = 0 Then
bTable = bTable & "</tr></table></div></div><div id='bing_opt' class='bingOpt'><div id='bing'><table><tr><td class='header'></td></tr><tr>"
ElseIf c Mod 4 = 0 Then
bTable = bTable & "</tr></table></div><div id='bing'><table><tr><td class='header'></td></tr><tr>"
ElseIf c Mod 2 = 0 And (c < 8 Or Not c = 12) Then
bTable = bTable & "</tr><tr>"
End If
End If
res = Split(elem.getAttribute("t2"), Chr(183))(0)
bTable = bTable + "<td><a dojoType='dojox.image.LightboxNano' title='Preview' href='" & imgurl &_
"'><img class='thumb' src='http://ts1.mm.bing.net/th?id=" & elem.getAttribute("ihk") & "&w=150&h=150'></a>" &_
"<span id='save' class='button' title='Save...' onclick='Download(""" & imgurl & """)'>&nbsp;</span>" & "<span>" & res & "</span></td>" & vbCrLf
c = c + 1
If c = 16 Then Exit For
Next
If Len(bTable) > 0 Then Bing = bmTable & bTable & "</table></div></div>"
End If
End With
End Function
Function Amazon(kwd)
Set hmac = CreateObject("System.Security.Cryptography.HMACSHA256")
Set ascii = CreateObject("System.Text.ASCIIEncoding")
akwd = uenc(kwd)
en = Split("( ) ' ,") : de = Split("%27 %28 %29 %2C")
For k = LBound(en) To UBound(en) : akwd = Replace(akwd, en(k), de(k)) : Next
DT = Year(Date()) & "-" & Pad(Month(Date())) & "-" & Pad(Day(Date())) & "T" & Pad(Hour(Now())) & ":" & Pad(Minute(Now())) & ":" & Pad(Second(Now())) & "Z"
DataString = "AWSAccessKeyId=AKIAJQ3PY445MLS5KN6Q&AssociateTag=delescenforgd-20&Keywords=" & akwd & "&Operation=ItemSearch&ResponseGroup=Images&SearchIndex=All&Service=AWSECommerceService&Timestamp=" & Escape(DT) & "&Version=2011-08-01"
Data = "GET" & vbLf & "webservices.amazon.com" & vbLf & "/onca/xml" & vbLf & DataString
hmac.Key = ascii.GetBytes_4("mTd4V3xsnzKD/LFnERB/zBjgfO+CdMwm/OLBClLa")
hash = hmac.ComputeHash_2((ASCII.GetBytes_4(Data)))
Signature = Replace(Escape(Base64Encode(hash)), "+", "%2B")
With CreateObject("MSXML2.DOMDocument.6.0")
.async = False
If .load("http://webservices.amazon.com/onca/xml?" & DataString & "&Signature=" & Signature) Then
.setProperty "SelectionLanguage", "XPath"
.setProperty "SelectionNamespaces", "xmlns:a='http://webservices.amazon.com/AWSECommerceService/2011-08-01'"
amTable = "<div id='amazon_l'><table><tr><td class='header'><span class='favicon' id='amazon'></span><a href='http://www.amazon.com/s?field-keywords=" & kwd & "' target='_blank' title='Open in browser'>more...</a></td></tr><tr>"
For Each elem In .selectNodes("//a:Items/a:Item/a:LargeImage")
If c Mod 4 = 0 And c <> 0 Then
aTable = aTable & "</tr></table></div><div id='amazon_r'><table><tr><td class='header'></td></tr><tr>" & vbCrLf
ElseIf c Mod 2 = 0 And c <> 0 Then
aTable = aTable & "</tr><tr>"
End If
aTable = aTable + "<td><a dojoType='dojox.image.LightboxNano' title='Preview' href='" & elem.selectSingleNode("a:URL").text &_
"'><img class='thumb' src='" & elem.parentNode.selectSingleNode("a:MediumImage/a:URL").text & "'></a>" &_
"<span class='button' id='save' title='Save...' onclick='Download(""" & elem.selectSingleNode("a:URL").text & """)'>&nbsp;</span>" &_
"<span>" & elem.selectSingleNode("a:Width").text & " x " & elem.selectSingleNode("a:Height").text & "</span></td>" & vbCrLf
c = c + 1
If c = 8 Then Exit For
Next
If Len(aTable) > 0 Then Amazon = amTable & aTable & "</table></div>"
End If
End With
End Function
Function Pad(n) : Pad = Right(String(2, "0") & n, 2) : End Function
Function Base64Encode(s)
Set dom = CreateObject("MSXML2.DOMDocument.3.0")
Set elem = dom.appendChild(dom.createElement("root"))
elem.dataType = "bin.base64"
elem.nodeTypedValue = s
Base64Encode = elem.Text
End Function
Function Fanart(album, artist)
With CreateObject("Microsoft.XMLDOM")
.async = False
.load("http://musicbrainz.org/ws/2/release-group/?limit=5&query=release:" & LuceneEscape(album) & " artist:" & LuceneEscape(artist) & " primarytype:Album")
Set mbid = .selectSingleNode("metadata/release-group-list/release-group[@ext:score='100' and title='" & album & "']/@id")
If Not mbid Is Nothing Then
.load("http://api.fanart.tv/webservice/album/930a0ee0b93c74cf323c7dc640ba9eb3/" & mbid.text & "/xml/all/1/2/")
fmTable = "<div id='fanart'><table><tr><td class='header'><span class='favicon' id='fanart'></span><a href='http://fanart.tv/api/getdata.php?s=" & uenc(kwd) & "&type=2' target='_blank' title='Open in browser'>more...</a></td></tr><tr>"
For Each albumcover In .selectNodes("fanart/music/albums/album[0]/albumcover")
If c Mod 2 = 0 And c <> 0 Then fTable = fTable & "</tr><tr>"
fTable = ftable & "<td><a dojoType='dojox.image.LightboxNano' title='Preview' href='" & albumcover.getAttribute("url") &_
"'><img class='thumb' src='" & albumcover.getAttribute("url") & "/preview" & "'></a>" &_
"<span class='button' id='save' title='Save...' onclick='Download(""" & albumcover.getAttribute("url") & """)'>&nbsp;</span></td>" & vbCrLf
c = c + 1
If c = 4 Then Exit For
Next
For Each cdart In .selectNodes("fanart/music/albums/album[0]/cdart")
If c Mod 2 = 0 And c <> 0 Then fTable = fTable & "</tr><tr>"
fTable = ftable & "<td><a dojoType='dojox.image.LightboxNano' title='Preview' href='" & cdart.getAttribute("url") &_
"'><img class='thumb' src='" & cdart.getAttribute("url") & "/preview" & "'></a>" &_
"<span class='button' id='save' title='Save...' onclick='Download(""" & cdart.getAttribute("url") & """)'>&nbsp;</span></td>" & vbCrLf
c = c + 1
If c = 4 Then Exit For
Next
End If
End With
If Len(fTable) > 0 Then Fanart = fmTable & fTable & "</table></div>"
End Function
Function LuceneEscape(s)
For Each k in Split("+ - && || ! ( ) { } [ ] ^ "" ~ * ? : \ / '") : s = Replace(s, k, "\" & k) : Next
LuceneEscape = uenc("""" & s & """")
End Function
Function Request(url)
On Error Resume Next
With CreateObject("MSXML2.XMLHTTP")
.open "GET", url, False
.send ""
If Not Err.number Then Request = .responseText
End With
End Function
Sub Download(url)
Set fso = CreateObject("Scripting.Filesystemobject")
If default_folder = "" Then default_folder = fso.GetParentFolderName(arg(1))
folder = default_folder
If Ubound(arg) > 6 Then folder = arg(7)
If default_filename = "" Then default_filename = "cover"
filename = default_filename
Set http = CreateObject("MSXML2.XMLHTTP")
http.open "GET", url, False
On Error Resume Next
http.Send
status = http.Status
On Error Goto 0
If status = 200 Then
path = Trim(InputBox("", "Save path", folder & "\" & filename & "." & fso.GetExtensionName(url)))
With CreateObject("ADODB.Stream")
.Type = 1
.Open
.Write http.responseBody
If fso.FolderExists(fso.GetParentFolderName(path)) Then .SaveToFile path, 2
End With
Else
msgbox "Not available!", 64, "Download Error"
End If
End Sub
Sub Research(w)
q = Trim(InputBox(vbCrLf & vbCrLf & vbCrLf & "Refine current keywords" & vbCrLf & "(separate album and artist by double colon):", "Search keywords", album & " :: " & artist))
q = Split(q, "::")
On Error Resume Next
If Trim(q(0)) <> album Or Trim(q(1)) <> artist Then
album = Trim(q(0)) : artist = Trim(q(1)) : kwd = album & " " & artist
document.body.innerHtml = "<div id='nav'></div>" & Google(kwd) & Amazon(kwd) & Bing(kwd) & Fanart(album, artist)
Resize w, 700
End If
On Error Goto 0
End Sub
Sub Resize(w, h)
Dim bing_main, bing_opt, amazon_l, amazon_r
With document
Set bing_main = .getElementById("bing_main") : Set bing_opt = .getElementById("bing_opt")
Set amazon_l = .getElementById("amazon_l") : Set amazon_r = .getElementById("amazon_r")
Set fan_art = .getElementById("fanart")
End With
spanDefault = "<span class='button' id='default' title='Show less' onclick='Resize(900,700);'>&nbsp;</span>"
If Not fan_art Is Nothing Then
If Not amazon_r Is Nothing Then
document.body.replaceChild fan_art, amazon_r
ElseIf Not bing_main Is Nothing Then
prependNode bing_main, fan_art
End If
End If
If bing_main Is Nothing Then
w = 600
If amazon_l Is Nothing Then
document.body.style.height = "350px"
Else
amazon_l.style.styleFloat = "left"
End If
ElseIf amazon_l Is Nothing Then
document.body.style.backgroundColor = "#FFB900"
If bing_opt Is Nothing Then
w = 600
Else
bing_opt.style.display = "block"
swapNodes bing_main, bing_opt
End If
ElseIf Not bing_opt Is Nothing Then
spanWide = "<span class='button' id='wide' title='Show more' onclick='Resize(1200, 700);'>&nbsp;</span>"
If w = 900 Then
amazon_l.style.width = "300px"
amazon_l.style.styleFloat = "right"
bing_opt.style.display = "none"
Else
If amazon_r Is Nothing And fan_art Is Nothing Then amazon_l.style.width = "600px"
bing_main.style.styleFloat = "left"
bing_opt.style.display = "block"
bing_opt.style.width = "600px"
End If
End If
With document.getElementById("nav")
Select Case w
Case 1200 .innerHtml = spanDefault
Case 900 .innerHtml = spanWide
End Select
End With
ResizeTo w, h
ResizeTo 2*w - document.documentElement.offsetWidth, 2*h - document.documentElement.offsetHeight
document.body.style.width = w & "px"
document.body.style.height = h & "px"
End Sub
Sub Resized(w, h)
ResizeTo w, h
ResizeTo 2*w - document.documentElement.offsetWidth, 2*h - document.documentElement.offsetHeight
MoveTo (screen.AvailWidth-w)/2, (screen.AvailHeight-h)/2
End Sub
Sub Window_OnLoad()
If kwd <> "" Then
Resized 900, 700
document.title = album & " :: " & artist
document.body.innerHtml = document.body.innerHtml & Google(kwd) & Amazon(kwd) & Bing(kwd) & Fanart(album, artist)
Resize 900, 700
End If
End Sub
Sub Document_onKeyDown()
If Window.Event.KeyCode = 27 Then window.close
If Window.Event.KeyCode = 82 And window.event.ctrlKey Then Research(900)
End Sub
</script>
<body>
<div id='nav'></div>
</body>
</html>
@rornor
Copy link
Author

rornor commented Jul 15, 2013

Thread: http://www.hydrogenaudio.org/forums/index.php?showtopic=100660

Usage: cover_search.hta "%album%" "%artist%" ["$directory_path(%path%)"]

Version with bigger thumbs: https://gist.github.com/c53dab9e9763057e0a9a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment