From 864081102a5f252415f41950b3039a896b4ae9c5 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Mon, 8 Oct 2012 18:43:29 +0000 Subject: Awkwars's plugins - welcome to our trunk git-svn-id: http://svn.miranda-ng.org/main/trunk@1822 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Watrack/lastfm/i_last_api.inc | 599 ++++++++++++++++++++++++++++++++++ 1 file changed, 599 insertions(+) create mode 100644 plugins/Watrack/lastfm/i_last_api.inc (limited to 'plugins/Watrack/lastfm/i_last_api.inc') diff --git a/plugins/Watrack/lastfm/i_last_api.inc b/plugins/Watrack/lastfm/i_last_api.inc new file mode 100644 index 0000000000..73328366ba --- /dev/null +++ b/plugins/Watrack/lastfm/i_last_api.inc @@ -0,0 +1,599 @@ +{} + +const + client_id = 'wat';//'wat'; 'tst' + client_ver = '1.0'; + api_key = '51f5d25159da31b0814609c3a12900e2'; + +const + defreq = 'http://post.audioscrobbler.com/?hs=true&p=1.2.1&c=&v=&u=&t=&a='; + +function GetMD5Str(digest:TMD5Hash; buf:pAnsiChar):PAnsiChar; +begin + buf[00]:=HexDigitChrLo[digest[00] shr 4]; buf[01]:=HexDigitChrLo[digest[00] and $0F]; + buf[02]:=HexDigitChrLo[digest[01] shr 4]; buf[03]:=HexDigitChrLo[digest[01] and $0F]; + buf[04]:=HexDigitChrLo[digest[02] shr 4]; buf[05]:=HexDigitChrLo[digest[02] and $0F]; + buf[06]:=HexDigitChrLo[digest[03] shr 4]; buf[07]:=HexDigitChrLo[digest[03] and $0F]; + buf[08]:=HexDigitChrLo[digest[04] shr 4]; buf[09]:=HexDigitChrLo[digest[04] and $0F]; + buf[10]:=HexDigitChrLo[digest[05] shr 4]; buf[11]:=HexDigitChrLo[digest[05] and $0F]; + buf[12]:=HexDigitChrLo[digest[06] shr 4]; buf[13]:=HexDigitChrLo[digest[06] and $0F]; + buf[14]:=HexDigitChrLo[digest[07] shr 4]; buf[15]:=HexDigitChrLo[digest[07] and $0F]; + buf[16]:=HexDigitChrLo[digest[08] shr 4]; buf[17]:=HexDigitChrLo[digest[08] and $0F]; + buf[18]:=HexDigitChrLo[digest[09] shr 4]; buf[19]:=HexDigitChrLo[digest[09] and $0F]; + buf[20]:=HexDigitChrLo[digest[10] shr 4]; buf[21]:=HexDigitChrLo[digest[10] and $0F]; + buf[22]:=HexDigitChrLo[digest[11] shr 4]; buf[23]:=HexDigitChrLo[digest[11] and $0F]; + buf[24]:=HexDigitChrLo[digest[12] shr 4]; buf[25]:=HexDigitChrLo[digest[12] and $0F]; + buf[26]:=HexDigitChrLo[digest[13] shr 4]; buf[27]:=HexDigitChrLo[digest[13] and $0F]; + buf[28]:=HexDigitChrLo[digest[14] shr 4]; buf[29]:=HexDigitChrLo[digest[14] and $0F]; + buf[30]:=HexDigitChrLo[digest[15] shr 4]; buf[31]:=HexDigitChrLo[digest[15] and $0F]; + buf[32]:=#0; + result:=@buf; +end; + +function GetMD5(const data;datalen:integer;var digest:TMD5Hash):TMD5Hash; +begin + FillChar(digest,16,0); + + mir_md5_hash(pmir_md5_byte_t(data),datalen,digest); + + result:=digest; +end; + +function HandShake(login, password:PAnsiChar; notify:bool=false):bool; +var + buf:array [0..32] of AnsiChar; + digest:TMD5Hash; + stat:mir_md5_state_t; + timestamp:array [0..31] of AnsiChar; + request:array [0..511] of AnsiChar; + tmp,res:pAnsiChar; +begin + result:=false; + GetMD5Str(GetMD5(password,StrLen(password),digest),buf); + mir_md5_init(@stat); + mir_md5_append(@stat,@buf,32); + IntToStr(timestamp,GetCurrentTime); + mir_md5_append(@stat,@timestamp,StrLen(timestamp)); + mir_md5_finish(@stat,digest); + GetMD5Str(digest,buf); + StrCopy(request,defreq); + StrReplace(request,'' ,client_id); + StrReplace(request,'',client_ver); + StrReplace(request,'' ,login); + StrReplace(request,'' ,timestamp); + StrReplace(request,'' ,buf); + + res:=SendRequest(request,REQUEST_GET); + if (res<>nil) and (uint_ptr(res)>$0FFF) then + begin + if StrCmp(CharReplace(res,#10,#0),'OK')=0 then + begin + result:=true; + tmp:=StrEnd(res)+1; StrDup(session_id,tmp); + tmp:=StrEnd(tmp)+1; StrDup(np_url ,tmp); + tmp:=StrEnd(tmp)+1; StrDup(sub_url ,tmp); + end + else if notify then + begin + tmp:=StrCopyE(request,Translate('Last.fm error: ')); + if StrCmp(res,'BANNED' )=0 then StrCopy(tmp,Translate('Client is banned')) + else if StrCmp(res,'BADAUTH' )=0 then StrCopy(tmp,Translate('Bad Auth. Check login and password')) + else if StrCmp(res,'BADTIME' )=0 then StrCopy(tmp,Translate('Bad TimeStamp')) + else if StrCmp(res,'FAILED',6)=0 then StrCopy(tmp,res+7); + CallService(MS_POPUP_SHOWMESSAGEW,wparam(@request),SM_ERROR); + end; + mFreeMem(res); + end; +end; + +function encode(dst,src:pAnsiChar):PAnsiChar; +begin + while src^<>#0 do + begin + if not (src^ in [' ','%','+','&','?',#128..#255]) then + dst^:=src^ + else + begin + dst^:='%'; inc(dst); + dst^:=HexDigitChr[ord(src^) shr 4]; inc(dst); + dst^:=HexDigitChr[ord(src^) and $0F]; + end; + inc(src); + inc(dst); + end; + dst^:=#0; + result:=dst; +end; + +function SendNowPlaying:integer; +var + si:pSongInfoA; + buf :array [0..31 ] of AnsiChar; + args :array [0..1023] of AnsiChar; + res,pc:PAnsiChar; +begin + result:=-1; + if session_id<>nil then + begin + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UTF8,0)); + + pc:=@args; + pc:=StrCopyE(pc,'s='); pc:=StrCopyE(pc,session_id); //'?s=' + pc:=StrCopyE(pc,'&a='); + if si^.artist=nil then pc:=StrCopyE(pc,'Unknown') + else pc:=encode(pc,si^.artist); + pc:=StrCopyE(pc,'&t='); + if si^.title =nil then pc:=StrCopyE(pc,'Unknown') + else pc:=encode(pc,si^.title); + pc:=StrCopyE(pc,'&l='); if si^.total>0 then pc:=StrCopyE(pc,IntToStr(buf,si^.total)); + pc:=StrCopyE(pc,'&b='); pc:=encode(pc,si^.album); + pc:=StrCopyE(pc,'&n='); + if si^.track<>0 then + {pc:=}StrCopyE(pc,IntToStr(buf,si^.track)); + + res:=SendRequest(np_url,REQUEST_POST,args); + if (res<>nil) and (uint_ptr(res)>$0FFF) then + begin + if StrCmp(CharReplace(res,#10,#0),'OK')=0 then + result:=1 + else if StrCmp(res,'BADSESSION')=0 then + result:=-1; + mFreeMem(res); + end; + end; +end; + +function Scrobble:integer; +var + si:pSongInfoA; + buf,timestamp:array [0..31] of AnsiChar; + args :array [0..1023] of AnsiChar; + res,pc:PAnsiChar; +begin + result:=-1; + if session_id<>nil then + begin + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UTF8,0)); + IntToStr(timestamp,GetCurrentTime); + + pc:=@args; + pc:=StrCopyE(pc,'s=' ); pc:=StrCopyE(pc,session_id); + pc:=StrCopyE(pc,'&a[0]='); + if si^.artist=nil then pc:=StrCopyE(pc,'Unknown') + else pc:=encode(pc,si^.artist); + pc:=StrCopyE(pc,'&t[0]='); + if si^.title =nil then pc:=StrCopyE(pc,'Unknown') + else pc:=encode(pc,si^.title); + pc:=StrCopyE(pc,'&i[0]='); pc:=StrCopyE(pc,timestamp); + pc:=StrCopyE(pc,'&r[0]=&m[0]='); + pc:=StrCopyE(pc,'&l[0]='); + if si^.total>0 then + begin + pc:=StrCopyE(pc,IntToStr(buf,si^.total)); + pc:=StrCopyE(pc,'&o[0]=P'); + end + else + begin + pc:=StrCopyE(pc,'&o[0]=R'); + end; + pc:=StrCopyE(pc,'&b[0]='); pc:=encode(pc,si^.album); + pc:=StrCopyE(pc,'&n[0]='); + if si^.track<>0 then + {pc:=}StrCopyE(pc,IntToStr(buf,si^.track)); + + res:=SendRequest(sub_url,REQUEST_POST,args); + if (res<>nil) and (uint_ptr(res)>$0FFF) then + begin + if StrCmp(CharReplace(res,#10,#0),'OK')=0 then + result:=1 + else if StrCmp(res,'BADSESSION')=0 then + begin + result:=-1; + end + else if StrCmp(res,'FAILED',6)=0 then + begin + StrCopy(StrCopyE(args,Translate('Last.fm error: ')),res+7); + CallService(MS_POPUP_SHOWMESSAGE,wparam(@args),SM_NOTIFY); + result:=0; + end; + mFreeMem(res); + end; + end; +end; + +//----- Get Info service functions ----- + +function FullEncode(dst,src:pAnsiChar):PAnsiChar; +begin + while src^<>#0 do + begin + if src^ in ['A'..'Z','a'..'z','0'..'9'] then + dst^:=src^ + else + begin + dst^:='%'; inc(dst); + dst^:=HexDigitChr[ord(src^) shr 4]; inc(dst); + dst^:=HexDigitChr[ord(src^) and $0F]; + end; + inc(src); + inc(dst); + end; + dst^:=#0; + result:=dst; +end; + +var + xmlparser:XML_API_W; + +function FixInfo(info:pWideChar):pWideChar; +var + pc,ppc:pWideChar; + cnt:cardinal; + need:boolean; +begin + pc:=info; + cnt:=0; + need:=false; + while pc^<>#0 do + begin + if pc^=#$0D then + begin + inc(cnt); + inc(pc); + if pc^<>#$0A then + need:=true; + end + else + inc(pc); + end; + if need then + begin + mGetMem(result,(StrLenW(info)+1+cnt)*SizeOf(WideChar)); + pc:=info; + ppc:=result; + while pc^<>#0 do + begin + ppc^:=pc^; + if pc^=#$0D then + begin + inc(ppc); + ppc^:=#$0A; + end; + inc(pc); + inc(ppc); + end; + ppc^:=#0; + end + else + StrDupW(result,info); +end; + +function GetArtistInfo(var data:tLastFMInfo;lang:integer):int; +var + si:pSongInfo; + res,pc:pAnsiChar; + request:array [0..1023] of AnsiChar; + root,actnode,node,nnode:HXML; + i:integer; + pcw,p,pp:PWideChar; + artist:pAnsiChar; +begin + result:=0; + if data.artist=nil then + begin + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0)); + pWideChar(artist):=si^.artist; + end + else + pWideChar(artist):=data.artist; + if artist=nil then + exit; + WideToUTF8(pWideChar(artist),artist); + pc:=FullEncode(StrCopyE(request, + 'http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key='+api_key+'&artist='), + artist); + mFreeMem(artist); + if lang<>0 then + StrCopyE(StrCopyE(pc,'&lang='),pAnsiChar(@lang)); + res:=SendRequest(request,REQUEST_GET); + if (res<>nil) and (uint_ptr(res)>$0FFF) then + begin + UTF8ToWide(res,pcw); + mFreeMem(res); + xmlparser.cbSize:={XML_API_SIZEOF_V1;//}SizeOf(XML_API_W); + CallService(MS_SYSTEM_GET_XI,0,lparam(@xmlparser)); + with xmlparser do + begin + i:=StrLenW(pcw)*SizeOf(WideChar); + root:=parseString(pcw,@i,nil); + + actnode:=getChild(getChild(root,0),0); // "artist" + + if data.artist=nil then + StrDupW(data.artist,getText(GetNthChild(actnode,'name',0))); + + i:=0; + repeat + node:=GetNthChild(actnode,'image',i); + if node=0 then break; + if StrCmpW(GetAttrValue(node,'size'),'medium')=0 then + begin + WideToUTF8(GetText(node),data.image); + break; + end; + inc(i); + until false; + + // bio + p:=StrPosW(pcw,'nil then + begin + inc(p,18); + pp:=StrPosW(p,']]'); + if pp<> nil then pp^:=#0; + data.info:=FixInfo(p); + end; + + // similar + i:=0; + pcw:=pWideChar(@request); pcw^:=#0; + node:=GetNthChild(actnode,'similar',0); + repeat + nnode:=GetNthChild(GetNthChild(node,'artist',i),'name',0); + if nnode=0 then break; + if pcw<>@request then + begin + pcw^:=','; inc(pcw); + pcw^:=' '; inc(pcw); + end; + pcw:=StrCopyEW(pcw,GetText(nnode)); + inc(i); + until false; + pcw:=#0; + StrDupW(data.similar,pWideChar(@request)); + + // tags + i:=0; + pcw:=pWideChar(@request); pcw^:=#0; + node:=GetNthChild(actnode,'tags',0); + repeat + nnode:=GetNthChild(GetNthChild(node,'tag',i),'name',0); + if nnode=0 then break; + if pcw<>@request then + begin + pcw^:=','; inc(pcw); + pcw^:=' '; inc(pcw); + end; + pcw:=StrCopyEW(pcw,GetText(nnode)); + inc(i); + until false; + pcw:=#0; + StrDupW(data.tags,pWideChar(@request)); + DestroyNode(root); + mFreeMem(pcw); + end; + end; +end; + +function GetAlbumInfo(var data:tLastFMInfo;lang:integer):int; +var + si:pSongInfo; + res,pc:pAnsiChar; + request:array [0..1023] of AnsiChar; + root,actnode,node,nnode:HXML; + i:integer; + p,pp,pcw:PWideChar; + album,artist:pAnsiChar; +begin + result:=0; + si:=nil; + if data.album=nil then + begin + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0)); + pWideChar(album):=si^.album; + end + else + pWideChar(album):=data.album; + if album=nil then + exit; + WideToUTF8(pWideChar(album),album); + pc:=FullEncode(StrCopyE(request, + 'http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key='+api_key+'&album='), + album); + mFreeMem(album); + if data.artist=nil then + begin + if si=nil then + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0)); + pWideChar(artist):=si^.artist; + end + else + pWideChar(artist):=data.artist; + if artist<>nil then + begin + WideToUTF8(pWideChar(artist),artist); + pc:=FullEncode(StrCopyE(pc,'&artist='),artist); + mFreeMem(artist); + end; + + if lang<>0 then + StrCopyE(StrCopyE(pc,'&lang='),pAnsiChar(@lang)); + + res:=SendRequest(request,REQUEST_GET); + if res<>nil then + begin + UTF8ToWide(res,pcw); + mFreeMem(res); + xmlparser.cbSize:={XML_API_SIZEOF_V1;//}SizeOf(XML_API_W); + CallService(MS_SYSTEM_GET_XI,0,lparam(@xmlparser)); + with xmlparser do + begin + i:=StrLenW(pcw)*SizeOf(WideChar); + root:=parseString(pcw,@i,nil); + + actnode:=getChild(getChild(root,0),0); // "album" + + if data.album=nil then + StrDupW(data.album,getText(GetNthChild(actnode,'name',0))); + StrDupW(data.release,getText(GetNthChild(actnode,'releasedate',0))); + if data.artist=nil then + StrDupW(data.artist,getText(GetNthChild(actnode,'artist',0))); + + i:=0; + repeat + node:=GetNthChild(actnode,'image',i); + if node=0 then break; + if StrCmpW(GetAttrValue(node,'size'),'medium')=0 then + begin + WideToUTF8(GetText(node),data.image); + break; + end; + inc(i); + until false; + + p:=StrPosW(pcw,'nil then + begin + inc(p,18); + pp:=StrPosW(p,']]'); + if pp<> nil then pp^:=#0; + data.info:=FixInfo(p); + end; + + // tags + i:=0; + pcw:=pWideChar(@request); pcw^:=#0; + node:=GetNthChild(actnode,'toptags',0); + repeat + nnode:=GetNthChild(GetNthChild(node,'tag',i),'name',0); + if nnode=0 then break; + if pcw<>@request then + begin + pcw^:=','; inc(pcw); + pcw^:=' '; inc(pcw); + end; + pcw:=StrCopyEW(pcw,GetText(nnode)); + inc(i); + until false; + pcw:=#0; + StrDupW(data.tags,pWideChar(@request)); + + DestroyNode(root); + mFreeMem(pcw); + end; + end; +end; + +function GetTrackInfo(var data:tLastFMInfo;lang:integer):int; +var + si:pSongInfo; + res,pc:pAnsiChar; + request:array [0..1023] of AnsiChar; + root,actnode,node,anode:HXML; + i:integer; + p,pp,pcw:PWideChar; + title,artist:pAnsiChar; +begin + result:=0; + si:=nil; + if data.album=nil then + begin + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0)); + pWideChar(title):=si^.title; + end + else + pWideChar(title):=data.title; + if title=nil then + exit; + WideToUTF8(pWideChar(title),title); + pc:=FullEncode(StrCopyE(request, + 'http://ws.audioscrobbler.com/2.0/?method=track.getinfo&api_key='+api_key+'&track='), + title); + mFreeMem(title); + if data.artist=nil then + begin + if si=nil then + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0)); + pWideChar(artist):=si^.artist; + end + else + pWideChar(artist):=data.artist; + if artist<>nil then + begin + WideToUTF8(pWideChar(artist),artist); + pc:=FullEncode(StrCopyE(pc,'&artist='),artist); + mFreeMem(artist); + end; + + if lang<>0 then + StrCopyE(StrCopyE(pc,'&lang='),pAnsiChar(@lang)); + + res:=SendRequest(request,REQUEST_GET); + if res<>nil then + begin + UTF8ToWide(res,pcw); + mFreeMem(res); + xmlparser.cbSize:={XML_API_SIZEOF_V1;//}SizeOf(XML_API_W); + CallService(MS_SYSTEM_GET_XI,0,lparam(@xmlparser)); + with xmlparser do + begin + i:=StrLenW(pcw)*SizeOf(WideChar); + root:=parseString(pcw,@i,nil); + + actnode:=getChild(getChild(root,0),0); // "track" + if data.artist=nil then + StrDupW(data.artist,getText(GetNthChild(GetNthChild(actnode,'artist',0),'name',0))); + + anode:=GetNthChild(actnode,'album',i); + + if data.album=nil then + StrDupW(data.album,getText(GetNthChild(anode,'title',0))); + + data.trknum:=StrToInt(getAttrValue(anode,'position')); + if data.title=nil then + StrDupW(data.title,getText(GetNthChild(actnode,'name',0))); + + i:=0; + repeat + node:=GetNthChild(anode,'image',i); + if node=0 then break; + if StrCmpW(GetAttrValue(node,'size'),'medium')=0 then + begin + WideToUTF8(GetText(node),data.image); + break; + end; + inc(i); + until false; + + p:=StrPosW(pcw,'nil then + begin + inc(p,18); + pp:=StrPosW(p,']]'); + if pp<> nil then pp^:=#0; + data.info:=FixInfo(p); + end; + + // tags + i:=0; + pcw:=pWideChar(@request); pcw^:=#0; + node:=GetNthChild(actnode,'toptags',0); + repeat + anode:=GetNthChild(GetNthChild(node,'tag',i),'name',0); + if anode=0 then break; + if pcw<>@request then + begin + pcw^:=','; inc(pcw); + pcw^:=' '; inc(pcw); + end; + pcw:=StrCopyEW(pcw,GetText(anode)); + inc(i); + until false; + pcw:=#0; + StrDupW(data.tags,pWideChar(@request)); + + DestroyNode(root); + mFreeMem(pcw); + end; + end; +end; -- cgit v1.2.3