diff --git a/Action.php b/Action.php index 46f0125..8ac5f90 100644 --- a/Action.php +++ b/Action.php @@ -174,21 +174,14 @@ var Meting{$PID} = new APlayer({ $id=$this->request->get('id'); $site=$this->request->get('site'); - $cachekey="lrc/{$site}/{$id}"; + $cachekey="lyric/{$site}/{$id}"; $data=self::cacheRead($cachekey,60*60*24*10); if(!$data){ - $data=(new Meting($site))->lyric($id); + $data=(new Meting($site))->format(true)->lyric($id); $data=json_decode($data,1); self::cacheWrite($cachekey,$data); } - - switch($site){ - case 'netease':$text=$data['lrc']['lyric'];break; - case 'tencent':$text=base64_decode($data['lyric']);break; - case 'xiami':$text=$data['lyric'];break; - case 'kugou':$text=$data['lyric'];break; - case 'baidu':$text=$data['lrcContent'];break; - } + $text=$data['lyric']; if(strlen($text)==0)$text='[00:00.00]无歌词'; echo $text; } diff --git a/Plugin.php b/Plugin.php index 749126c..d60bc7b 100644 --- a/Plugin.php +++ b/Plugin.php @@ -6,13 +6,13 @@ if(!defined('__TYPECHO_ROOT_DIR__'))exit; * * @package Meting * @author METO - * @version 1.0.2 + * @version 1.0.3 * @dependence 13.12.12-* * @link https://github.com/metowolf/Meting * */ - define('METING_VERSION','1.0.2'); +define('METING_VERSION','1.0.3'); class Meting_Plugin extends Typecho_Widget implements Typecho_Plugin_Interface { diff --git a/include/Meting.php b/include/Meting.php index 1870eb6..720e345 100644 --- a/include/Meting.php +++ b/include/Meting.php @@ -2,7 +2,7 @@ /*! * Meting music framework * https://i-meto.com - * Version 1.0.2 + * Version 1.1.1 * * Copyright 2016, METO Sheel * Released under the MIT license @@ -12,14 +12,29 @@ class Meting { protected $_SITE; protected $_TEMP; + protected $_RETRY = 3; protected $_FORMAT = false; - function __construct($v='netease'){ - self::site($v); + private $data; + private $info; + private $error; + private $status; + + public function __construct($v='netease'){ + $this->site($v); + } + + public function __toString(){ + if($this->error)return json_encode(array( + 'code'=>$this->error, + 'status'=>$this->status, + )); + return $this->data; } public function site($v){ $this->_SITE=$v; + return $this; } public function format($v = true){ @@ -29,53 +44,56 @@ class Meting private function curl($API){ if(isset($API['encode']))$API=call_user_func_array(array($this,$API['encode']),array($API)); - - $BASE=self::curlset(); + $BASE=$this->curlset(); $curl=curl_init(); if($API['method']=='POST'){ if(is_array($API['body']))$API['body']=http_build_query($API['body']); - curl_setopt($curl,CURLOPT_URL,$API['url']); - curl_setopt($curl,CURLOPT_POSTFIELDS,$API['body']); curl_setopt($curl,CURLOPT_POST,1); + curl_setopt($curl,CURLOPT_POSTFIELDS,$API['body']); } elseif($API['method']=='GET'){ if(isset($API['body']))$API['url']=$API['url'].'?'.http_build_query($API['body']); - curl_setopt($curl,CURLOPT_URL,$API['url']); } - curl_setopt($curl,CURLOPT_RETURNTRANSFER,1); - curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,10); + curl_setopt($curl,CURLOPT_HEADER,0); curl_setopt($curl,CURLOPT_TIMEOUT,20); + curl_setopt($curl,CURLOPT_ENCODING,''); + curl_setopt($curl,CURLOPT_IPRESOLVE,1); + curl_setopt($curl,CURLOPT_RETURNTRANSFER,1); + curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,0); + curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,10); + curl_setopt($curl,CURLOPT_URL,$API['url']); curl_setopt($curl,CURLOPT_COOKIE,$BASE['cookie']); curl_setopt($curl,CURLOPT_REFERER,$BASE['referer']); curl_setopt($curl,CURLOPT_USERAGENT,$BASE['useragent']); - $result=curl_exec($curl); - curl_close($curl); - - if(isset($API['decode']))$result=call_user_func_array(array($this,$API['decode']),array($result)); - - if($this->_FORMAT){ - if(isset($API['format'])){ - $result=json_decode($result,1); - $result=self::clean($result,$API['format']); - $result=json_encode($result); - } - $this->_FORMAT=false; + for($i=0;$i<=$this->_RETRY;$i++){ + $this->data=curl_exec($curl); + $this->info=curl_getinfo($curl); + $this->error=curl_errno($curl); + $this->status=$this->error?curl_error($curl):''; + if(!$this->error)break; } - return $result; + curl_close($curl); + if(isset($API['decode']))$this->data=call_user_func_array(array($this,$API['decode']),array($this->data)); + if($this->_FORMAT&&isset($API['format'])){ + $this->data=json_decode($this->data,1); + $this->data=$this->clean($this->data,$API['format']); + $this->data=json_encode($this->data); + } + return $this; } private function pickup($array,$rule){ $t=explode('#',$rule); foreach($t as $vo){ - if($array==null)return null; + if(is_null($array))return null; $array=$array[$vo]; } return $array; } private function clean($raw,$rule){ - if(!empty($rule))$raw=self::pickup($raw,$rule); - if($raw==null)$raw=array(); + if(!empty($rule))$raw=$this->pickup($raw,$rule); + if(is_null($raw))$raw=array(); elseif(!isset($raw[0]))$raw=array($raw); $result=array_map(array($this,'format_'.$this->_SITE),$raw); return $result; @@ -161,7 +179,7 @@ class Meting 'format' => 'result#song_info#song_list', ), ); - return self::curl($API[$this->_SITE]); + return $this->curl($API[$this->_SITE]); } public function song($id){ @@ -226,7 +244,7 @@ class Meting 'format' => 'songinfo', ), ); - return self::curl($API[$this->_SITE]); + return $this->curl($API[$this->_SITE]); } public function album($id){ @@ -291,7 +309,7 @@ class Meting 'format' => 'songlist', ), ); - return self::curl($API[$this->_SITE]); + return $this->curl($API[$this->_SITE]); } public function artist($id,$limit=50){ @@ -363,7 +381,7 @@ class Meting 'format' => 'songlist', ), ); - return self::curl($API[$this->_SITE]); + return $this->curl($API[$this->_SITE]); } public function playlist($id){ @@ -432,7 +450,7 @@ class Meting 'format' => 'content', ), ); - return self::curl($API[$this->_SITE]); + return $this->curl($API[$this->_SITE]); } public function url($id,$br=320){ @@ -469,21 +487,20 @@ class Meting 'kugou'=>array( 'method' => 'POST', 'url' => 'http://media.store.kugou.com/v1/get_res_privilege', - 'body' => array( + 'body' => json_encode(array( "relate" => 1, "userid" => 0, "vip" => 0, - "appid" => 1390, + "appid" => 1005, "token" => "", "behavior" => "download", - "clientver" => "1", + "clientver" => "8493", "resource" => array(array( "id" => 0, "type" => "audio", "hash" => $id, - )), + ))) ), - 'encode' => 'kugou_json', 'decode' => 'kugou_url', ), 'baidu' => array( @@ -498,7 +515,7 @@ class Meting ), ); $this->_temp['br']=$br; - return self::curl($API[$this->_SITE]); + return $this->curl($API[$this->_SITE]); } public function lyric($id){ @@ -518,15 +535,16 @@ class Meting 'url' => 'http://music.163.com/api/song/lyric', ), 'encode' => 'netease_AESECB', + 'decode' => 'netease_lyric', ), 'tencent'=>array( 'method' => 'GET', - 'url' => 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric.fcg', + 'url' => 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg', 'body' => array( 'songmid' => $id, - 'nobase64' => 0, + 'g_tk' => 5381, ), - 'decode' => 'jsonp2json', + 'decode' => 'tencent_lyric', ), 'xiami'=>array( 'method' => 'GET', @@ -563,44 +581,39 @@ class Meting 'from' => 'ios', 'version' => '5.9.5', ), + 'decode' => 'baidu_lyric' ), ); - return self::curl($API[$this->_SITE]); + return $this->curl($API[$this->_SITE]); } public function pic($id,$size=300){ switch($this->_SITE){ case 'netease': - $url='https://p3.music.126.net/'.self::netease_pickey($id).'/'.$id.'.jpg?param='.$size.'z'.$size.'&quality=100'; + $url='https://p3.music.126.net/'.$this->netease_pickey($id).'/'.$id.'.jpg?param='.$size.'z'.$size.'&quality=100'; break; case 'tencent': $url='https://y.gtimg.cn/music/photo_new/T002R'.$size.'x'.$size.'M000'.$id.'.jpg?max_age=2592000'; break; case 'xiami': - $data=$this->format(false)->song($id); + $format=$this->_FORMAT; + $data=$this->format(false)->song($id)->format($format); $url=json_decode($data,1)['data']['song']['logo']; - $url=str_replace(['_1.','http:','img.'],['.','https:','pic.'],$url).'@'.$size.'h_'.$size.'w_90q_1c.webp'; + $url=str_replace(['_1.','http:','img.'],['.','https:','pic.'],$url).'@'.$size.'h_'.$size.'w_100q_1c.jpg'; break; case 'kugou': - $API=array( - 'method' =>'GET', - 'url' => 'http://tools.mobile.kugou.com/api/v1/singer_header/get_by_hash', - 'body' => array( - 'hash' => $id, - 'size' => 400, - 'format' => 'json', - ), - ); - $data=$this->curl($API); - $url=json_decode($data,1)['url']; + $format=$this->_FORMAT; + $data=$this->format(false)->song($id)->format($format); + $url=json_decode($data,1)['imgUrl']; + $url=str_replace('{size}','400',$url); break; case 'baidu': - $data=self::song($id); + $format=$this->_FORMAT; + $data=$this->format(false)->song($id)->format($format); $data=json_decode($data,1); $url=$data['songinfo']['pic_big']?:$data['songinfo']['pic_small']; } - $arr=array('url'=>$url); - return json_encode($arr); + return json_encode(array('url'=>$url)); } private function curlset(){ @@ -608,27 +621,27 @@ class Meting 'netease'=>array( 'referer' => 'http://music.163.com/', 'cookie' => 'os=linux; appver=1.0.0.1026; osver=Ubuntu%2016.10; MUSIC_U=78d411095f4b022667bc8ec49e9a44cca088df057d987f5feaf066d37458e41c4a7d9447977352cf27ea9fee03f6ec4441049cea1c6bb9b6; __remember_me=true', - 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.30 Safari/537.36', + 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', ), 'tencent'=>array( 'referer' => 'http://y.qq.com/portal/player.html', 'cookie' => 'qqmusic_uin=12345678; qqmusic_key=12345678; qqmusic_fromtag=30; ts_last=y.qq.com/portal/player.html;', - 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.30 Safari/537.36', + 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', ), 'xiami'=>array( 'referer' => 'http://h.xiami.com/', 'cookie' => 'user_from=2;XMPLAYER_addSongsToggler=0;XMPLAYER_isOpen=0;_xiamitoken=123456789;', - 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.30 Safari/537.36', + 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', ), 'kugou'=>array( 'referer' => 'http://www.kugou.com/webkugouplayer/flash/webKugou.swf', 'cookie' => '_WCMID=123456789', - 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.30 Safari/537.36', + 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', ), 'baidu'=>array( 'referer' => 'http://ting.baidu.com/', 'cookie' => 'BAIDUID=123456789', - 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.30 Safari/537.36', + 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', ), ); return $BASE[$this->_SITE]; @@ -655,10 +668,6 @@ class Meting ); return $API; } - private function kugou_json($API){ - $API['body']=json_encode($API['body']); - return $API; - } private function jsonp2json($jsonp){ if($jsonp[0] !== '[' && $jsonp[0] !== '{') { $jsonp = substr($jsonp, strpos($jsonp, '(')); @@ -785,7 +794,27 @@ class Meting * 歌词处理模块 * 用于规范化歌词输出 */ + private function netease_lyric($result){ + if(!$this->_FORMAT)return $result; + $result=json_decode($result,1); + $data=array( + 'lyric' => $result['lrc']['lyric'], + 'tlyric' => $result['tlyric']['lyric'], + ); + return json_encode($data); + } + private function tencent_lyric($result){ + $result=$this->jsonp2json($result); + if(!$this->_FORMAT)return $result; + $result=json_decode($result,1); + $data=array( + 'lyric' => base64_decode($result['lyric']), + 'tlyric' => base64_decode($result['trans']), + ); + return json_encode($data); + } private function xiami_lyric($result){ + if(!$this->_FORMAT)return $result; $result=json_decode($result,1); $API=array( 'method' => 'GET', @@ -799,11 +828,21 @@ class Meting return json_encode($arr); } private function kugou_lyric($result){ + if(!$this->_FORMAT)return $result; $arr=array( 'lyric' => $result, ); return json_encode($arr); } + private function baidu_lyric($result){ + if(!$this->_FORMAT)return $result; + $result=json_decode($result,1); + $data=array( + 'lyric' => $result['lrcContent'], + ); + return json_encode($data); + } + /** * Format - 规范化函数 * 用于统一返回的参数,可用 ->format() 一次性开关开启