diff --git a/Action.php b/Action.php index f75f6b3..c203b65 100644 --- a/Action.php +++ b/Action.php @@ -62,6 +62,10 @@ class Meting_Action extends Typecho_Widget implements Widget_Interface_Do { elseif(preg_match('/song\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'song'); elseif(preg_match('/artist\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'artist'); } + elseif(strpos($url,'kuwo.cn')!==false){ + $server='kuwo'; + if(preg_match('/yinyue\/(\d+)/i',$url,$id))list($id,$type)=array('MUSIC_'.$id[1],'song'); + } else list($id,$type)=array($url,'search'); echo '[Music server="'.$server.'" id="'.$id.'" type="'.$type.'"/]'."\n"; } @@ -214,8 +218,8 @@ class Meting_Action extends Typecho_Widget implements Widget_Interface_Do { private function cacheRead($k,$t=60*60){ $db=Typecho_Db::get(); $prefix=$db->getPrefix(); - $query= $db->select('value','date')->from($prefix.'meting')->where('id=?',sha1($k)); - $result = $db->fetchAll($query); + $query=$db->select('value','date')->from($prefix.'meting')->where('id=?',sha1($k)); + $result=$db->fetchAll($query); if(sizeof($result)){ if(time()-$result[0]['date']>$t){ $delete=$db->delete($prefix.'meting')->where('datefilter =array('Meting_Plugin','playerFilter'); Typecho_Plugin::factory('Widget_Abstract_Contents')->contentEx=array('Meting_Plugin','playerReplace'); Typecho_Plugin::factory('Widget_Abstract_Contents')->excerptEx=array('Meting_Plugin','playerReplace'); Typecho_Plugin::factory('Widget_Archive')->header=array('Meting_Plugin','header'); @@ -91,8 +90,6 @@ class Meting_Plugin extends Typecho_Widget implements Typecho_Plugin_Interface public static function personalConfig(Typecho_Widget_Helper_Form $form){} - public static function render(){} - /** * 获取插件配置面板 * @@ -114,12 +111,8 @@ class Meting_Plugin extends Typecho_Widget implements Typecho_Plugin_Interface return ++self::$PID; } - public static function playerFilter($data){ - return $data; - } - public static function playerReplace($data,$widget,$last){ - $text=$last?:$data; + $text=empty($last)?$data:$last; if($widget instanceof Widget_Archive){ $data=$text; $pattern=self::get_shortcode_regex(array('Meting')); @@ -142,7 +135,7 @@ class Meting_Plugin extends Typecho_Widget implements Typecho_Plugin_Interface $data=array(); foreach($matches as $vo){ $t=self::shortcode_parse_atts(htmlspecialchars_decode($vo)); - if(!in_array($t['server'],array('netease','tencent','xiami','baidu','kugou')))continue; + if(!in_array($t['server'],array('netease','tencent','xiami','baidu','kugou','kuwo')))continue; if(!in_array($t['type'],array('search','album','playlist','artist','song')))continue; $data[]=$t; } @@ -212,7 +205,7 @@ class Meting_Plugin extends Typecho_Widget implements Typecho_Plugin_Interface } }catch(Typecho_Db_Exception $e){ $code=$e->getCode(); - if($code=='42S01')return; + if($code=='42S01'||$code==1050)return; throw new Typecho_Plugin_Exception('数据表建立失败,插件启用失败。错误号: '.$code); } } diff --git a/include/Meting.php b/include/Meting.php index 720e345..c1393f7 100644 --- a/include/Meting.php +++ b/include/Meting.php @@ -2,9 +2,9 @@ /*! * Meting music framework * https://i-meto.com - * Version 1.1.1 + * Version 1.2.0.1 * - * Copyright 2016, METO Sheel + * Copyright 2017, METO Sheel * Released under the MIT license */ @@ -15,23 +15,10 @@ class Meting protected $_RETRY = 3; protected $_FORMAT = false; - 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; @@ -66,20 +53,25 @@ class Meting curl_setopt($curl,CURLOPT_REFERER,$BASE['referer']); curl_setopt($curl,CURLOPT_USERAGENT,$BASE['useragent']); 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; + $data=curl_exec($curl); + $info=curl_getinfo($curl); + $error=curl_errno($curl); + $status=$error?curl_error($curl):''; + if(!$error)break; } curl_close($curl); - if(isset($API['decode']))$this->data=call_user_func_array(array($this,$API['decode']),array($this->data)); + if($error)return json_encode(array( + 'error' => $error, + 'info' => $info, + 'status' => $status, + )); + if(isset($API['decode']))$data=call_user_func_array(array($this,$API['decode']),array($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); + $data=json_decode($data,1); + $data=$this->clean($data,$API['format']); + $data=json_encode($data); } - return $this; + return $data; } private function pickup($array,$rule){ @@ -178,6 +170,19 @@ class Meting ), 'format' => 'result#song_info#song_list', ), + 'kuwo' => array( + 'method' => 'GET', + 'url' => 'http://player.kuwo.cn/webmusic/getsjplayinfo', + 'body' => array( + 'flag' => 6, + 'pn' => 1, + 'pr' => 50, + 'type' => 'music', + 'key' => $keyword, + ), + 'decode' => 'kuwo_json', + 'format' => 'list', + ), ); return $this->curl($API[$this->_SITE]); } @@ -243,6 +248,15 @@ class Meting ), 'format' => 'songinfo', ), + 'kuwo' => array( + 'method' => 'GET', + 'url' => 'http://player.kuwo.cn/webmusic/st/getNewMuiseByRid', + 'body' => array( + 'rid' => $id, + ), + 'decode' => 'kuwo_singlesong', + 'format' => '', + ), ); return $this->curl($API[$this->_SITE]); } @@ -513,6 +527,17 @@ class Meting ), 'decode' => 'baidu_url', ), + 'kuwo' => array( + 'method' => 'GET', + 'url' => 'http://antiserver.kuwo.cn/anti.s', + 'body' => array( + 'response' => 'url', + 'format' => 'mp3|wav|aac', + 'type' => 'convert_url', + 'rid' => $id, + ), + 'decode' => 'kuwo_url', + ), ); $this->_temp['br']=$br; return $this->curl($API[$this->_SITE]); @@ -583,6 +608,11 @@ class Meting ), 'decode' => 'baidu_lyric' ), + 'kuwo' => array( + 'method' => 'GET', + 'url' => 'http://newlyric.kuwo.cn/newlyric.lrc?'.base64_encode($this->kuwo_xor("user=12345,web,web,web&requester=localhost&req=1&rid={$id}&lrcx=1")), + 'decode' => 'kuwo_lyric', + ), ); return $this->curl($API[$this->_SITE]); } @@ -597,21 +627,31 @@ class Meting break; case 'xiami': $format=$this->_FORMAT; - $data=$this->format(false)->song($id)->format($format); + $data=$this->format(false)->song($id); + $this->format($format); $url=json_decode($data,1)['data']['song']['logo']; $url=str_replace(['_1.','http:','img.'],['.','https:','pic.'],$url).'@'.$size.'h_'.$size.'w_100q_1c.jpg'; break; case 'kugou': $format=$this->_FORMAT; - $data=$this->format(false)->song($id)->format($format); + $data=$this->format(false)->song($id); + $this->format($format); $url=json_decode($data,1)['imgUrl']; $url=str_replace('{size}','400',$url); break; case 'baidu': $format=$this->_FORMAT; - $data=$this->format(false)->song($id)->format($format); + $data=$this->format(false)->song($id); + $this->format($format); $data=json_decode($data,1); $url=$data['songinfo']['pic_big']?:$data['songinfo']['pic_small']; + break; + case 'kuwo': + $API=array('method'=>'GET','url'=>'http://www.kuwo.cn/webmusic/sj/dtflagdate','body'=>array('flag'=>6,'rid'=>$id)); + $data=$this->curl($API); + $data=explode(',',$data); + $url=end(str_replace('http:','https:',$data)); + break; } return json_encode(array('url'=>$url)); } @@ -643,6 +683,11 @@ class Meting 'cookie' => 'BAIDUID=123456789', 'useragent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', ), + 'kuwo'=>array( + 'referer' => 'http://www.kuwo.cn/', + 'cookie' => '', + '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]; } @@ -674,6 +719,9 @@ class Meting } return trim($jsonp,'();'); } + private function kuwo_json($json){ + return str_replace("'",'"',$json); + } private function tencent_singlesong($result){ $result=json_decode($result,1); $data=$result['data'][0]; @@ -685,6 +733,29 @@ class Meting foreach($t as $key=>$vo)$result['data'][0][$key]=$vo; return json_encode($result); } + private function kuwo_singlesong($result){ + preg_match_all('/<([\w]+)>(.*?)<\/\\1>/i',$result,$matches); + for($i=0;$i $result, + 'br' => 192, + ); + return json_encode($url); + } /** * 歌词处理模块 * 用于规范化歌词输出 @@ -798,8 +876,8 @@ class Meting if(!$this->_FORMAT)return $result; $result=json_decode($result,1); $data=array( - 'lyric' => $result['lrc']['lyric'], - 'tlyric' => $result['tlyric']['lyric'], + 'lyric' => (@$result['lrc']['lyric'])?:'', + 'tlyric' => (@$result['tlyric']['lyric'])?:'', ); return json_encode($data); } @@ -808,20 +886,17 @@ class Meting if(!$this->_FORMAT)return $result; $result=json_decode($result,1); $data=array( - 'lyric' => base64_decode($result['lyric']), - 'tlyric' => base64_decode($result['trans']), + 'lyric' => isset($result['lyric'])?base64_decode($result['lyric']):'', + 'tlyric' => isset($result['trans'])?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', - 'url' => $result['data']['song']['lyric'], - ); + $API=array('method'=>'GET','url'=>$result['data']['song']['lyric']); $data=$this->curl($API); - $data=preg_replace('/<\d{1,8}>/','',$data); + $data=preg_replace('/<[^>]+>/','',$data); $arr=array( 'lyric' => $data, ); @@ -838,11 +913,23 @@ class Meting if(!$this->_FORMAT)return $result; $result=json_decode($result,1); $data=array( - 'lyric' => $result['lrcContent'], + 'lyric' => (@$result['lrcContent'])?:'', ); return json_encode($data); } - + private function kuwo_lyric($result){ + if(!$this->_FORMAT)return $result; + $str=substr($result,strpos($result,"\r\n\r\n")+4); + $str=zlib_decode($str); + $str=base64_decode($str); + $str=$this->kuwo_xor($str); + $str=iconv('gb18030',"UTF-8//IGNORE",$str); + $str=preg_replace('/<[^>]+>/','',$str); + $arr=array( + 'lyric' => $str, + ); + return json_encode($arr); + } /** * Format - 规范化函数 * 用于统一返回的参数,可用 ->format() 一次性开关开启 @@ -852,7 +939,7 @@ class Meting 'id' => $data['id'], 'name' => $data['name'], 'artist' => array(), - 'pic_id' => $data['al']['pic_str']?:$data['al']['pic'], + 'pic_id' => (@$data['al']['pic_str'])?:$data['al']['pic'], 'url_id' => $data['id'], 'lyric_id' => $data['id'], 'source' => 'netease', @@ -882,7 +969,7 @@ class Meting $result=array( 'id' => $data['song_id'], 'name' => $data['song_name'], - 'artist' => explode(';',$data['singers']?:$data['artist_name']), + 'artist' => explode(';',(@$data['singers'])?:$data['artist_name']), 'pic_id' => $data['song_id'], 'url_id' => $data['song_id'], 'lyric_id' => $data['song_id'], @@ -893,7 +980,7 @@ class Meting private function format_kugou($data){ $result=array( 'id' => $data['hash'], - 'name' => $data['filename']?:$data['fileName'], + 'name' => (@$data['filename'])?:$data['fileName'], 'artist' => array(), 'url_id' => $data['hash'], 'pic_id' => $data['hash'], @@ -916,4 +1003,16 @@ class Meting ); return $result; } + private function format_kuwo($data){ + $result=array( + 'id' => $data['rid'], + 'name' => $data['songName'], + 'artist' => explode('&',$data['artist']), + 'pic_id' => $data['rid'], + 'url_id' => $data['rid'], + 'lyric_id' => $data['rid'], + 'source' => 'kuwo', + ); + return $result; + } } diff --git a/include/uninstall.sql b/include/uninstall.sql index 154b44e..cbcff3b 100644 --- a/include/uninstall.sql +++ b/include/uninstall.sql @@ -1 +1 @@ -TRUNCATE typecho_meting; +DROP TABLE typecho_meting;