Skip to content

Commit

Permalink
🔥 2.0.0, 架构重写,支持自定义歌曲
Browse files Browse the repository at this point in the history
 - 重写前端逻辑
 - 支持自定义 API
 - 支持自定义歌曲
 - 去除 jQuery 依赖
 - 升级 Meting 库
  • Loading branch information
metowolf committed Sep 20, 2017
1 parent 9ca611c commit f120096
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 296 deletions.
343 changes: 148 additions & 195 deletions Action.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,217 +6,172 @@ class Meting_Action extends Typecho_Widget implements Widget_Interface_Do {
public function execute(){}

public function action(){
$this->on($this->request->is('do=musicjs'))->musicjs();
$this->on($this->request->is('do=url'))->url();
$this->on($this->request->is('do=pic'))->pic();
$this->on($this->request->is('do=lrc'))->lrc();
$this->on($this->request->is('do=parse'))->shortcode();
$this->on($this->request->isGet())->api();
}

private function shortcode(){
$urls=$this->request->get('data');
$urls=explode("\n",$urls);
echo "[Meting]\n";
foreach($urls as $url){
$url=trim($url);
if($url=="")continue;
$server='音乐平台';$id='编号';$type='类型';
if(strpos($url,'163.com')!==false){
$server='netease';
if(preg_match('/playlist\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
elseif(preg_match('/toplist\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
elseif(preg_match('/album\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'album');
elseif(preg_match('/song\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'song');
elseif(preg_match('/artist\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
}
elseif(strpos($url,'qq.com')!==false){
$server='tencent';
if(preg_match('/playlist\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
elseif(preg_match('/album\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'album');
elseif(preg_match('/song\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'song');
elseif(preg_match('/singer\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'artist');
}
elseif(strpos($url,'xiami.com')!==false){
$server='xiami';
if(preg_match('/collect\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
elseif(preg_match('/album\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'album');
elseif(preg_match('/[\/.]\w+\/[songdem]+\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'song');
elseif(preg_match('/artist\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
if(!preg_match('/^\d*$/i',$id,$t)){
$data=self::curl($url);
preg_match('/'.$type.'\/(\d+)/i',$data,$id);
$id=$id[1];
}
}
elseif(strpos($url,'kugou.com')!==false){
$server='kugou';
if(preg_match('/special\/single\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
elseif(preg_match('/song\/#hash\=(\w+)/i',$url,$id))list($id,$type)=array($id[1],'song');
elseif(preg_match('/album\/[single\/]*(\d+)/i',$url,$id))list($id,$type)=array($id[1],'album');
elseif(preg_match('/singer\/[home\/]*(\d+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
}
elseif(strpos($url,'baidu.com')!==false){
$server='baidu';
if(preg_match('/songlist\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
elseif(preg_match('/album\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'album');
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');
}
else list($id,$type)=array($url,'search');
echo '[Music server="'.$server.'" id="'.$id.'" type="'.$type.'"/]'."\n";
}
echo "[/Meting]";
private function check($a,$b){
if(!in_array($a,array('netease','tencent','baidu','xiami','kugou')))return false;
if(!in_array($b,array('song','album','search','artist','playlist','lrc','url','pic')))return false;
return true;
}

private function curl($url){
$curl=curl_init();
curl_setopt($curl,CURLOPT_URL,$url);
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,10);
curl_setopt($curl,CURLOPT_TIMEOUT,10);
curl_setopt($curl,CURLOPT_REFERER,$url);
$result=curl_exec($curl);
curl_close($curl);
return $result;
}
private function api(){
$this->filterReferer();
$server=$this->request->get('server');
$type=$this->request->get('type');
$id=$this->request->get('id');

if(!$this->check($server,$type)||empty($id))die('[]');

private function musicjs(){
if(!extension_loaded('Meting'))include_once 'include/Meting.php';
self::filterReferer();
$PID=$this->request->get('id');
$data=$this->request->get('d');
$data=json_decode(base64_decode($data),1);
$setting=$this->request->get('s');
$setting=json_decode(base64_decode($setting),1);
$music=array();
foreach($data as $vo){
$EID=md5('js/'.$vo['server'].'/'.$vo['type'].'/'.$vo['id']);
$t=self::cacheRead($EID,60*60*24*3);
if(!$t){
$API=(new \Metowolf\Meting($vo['server']))->format(true);
$t=call_user_func_array(array($API,$vo['type']),array($vo['id']));
$t=json_decode($t,1);
self::cacheWrite($EID,$t);
$api=new \Metowolf\Meting($server);
$api->format(true);

$EID=md5($server.'/'.$type.'/'.$id);
$salt=Typecho_Widget::widget('Widget_Options')->plugin('Meting')->salt;

if(in_array($type,array('lrc','pic','url'))){
$auth1=md5($salt.$id.$salt);
$auth2=$this->request->get('auth');
if(strcmp($auth1,$auth2)){
http_response_code(403);
die();
}
$music=array_merge($music,$t);
}
$player=array(
'theme' => isset($setting['theme'])?$setting['theme']:Typecho_Widget::widget('Widget_Options')->plugin('Meting')->theme?:'red',
'preload' => isset($setting['preload'])?$setting['preload']:Typecho_Widget::widget('Widget_Options')->plugin('Meting')->preload?:'auto',
'autoplay' => isset($setting['autoplay'])?$setting['autoplay']:Typecho_Widget::widget('Widget_Options')->plugin('Meting')->autoplay?:'false',
'height' => isset($setting['height'])?$setting['height']:Typecho_Widget::widget('Widget_Options')->plugin('Meting')->height?:'340px',
'mode' => isset($setting['mode'])?$setting['mode']:Typecho_Widget::widget('Widget_Options')->plugin('Meting')->mode?:'circulation',
'music' => array(),
);
foreach($music as $vo){
$URI=Typecho_Common::url('action/metingapi',Helper::options()->index);
$player['music'][]=array(
'title'=>$vo['name'],
'author'=>implode(' / ',$vo['artist']),
'url'=>$URI.'?site='.$vo['source'].'&do=url&id='.$vo['url_id'],
'pic'=>$URI.'?site='.$vo['source'].'&do=pic&id='.$vo['pic_id'],
'lrc'=>$URI.'?site='.$vo['source'].'&do=lrc&id='.$vo['lyric_id'],
);
}
if(sizeof($player['music'])==1)$player['music']=$player['music'][0];
$player['music']=json_encode($player['music']);

header('content-type:application/javascript');
echo "
var Meting{$PID} = new APlayer({
element: document.getElementById('MetingPlayer'+{$PID}),
autoplay: ".$player['autoplay'].",
preload: \"".$player['preload']."\",
showlrc: 3,
mutex: true,
mode: '".$player['mode']."',
theme: \"".$player['theme']."\",
music: ".$player['music'].",
listmaxheight: '".$player['height']."',
});
";
}

private function url(){
if(!extension_loaded('Meting'))include_once 'include/Meting.php';
self::filterReferer();
$id=$this->request->get('id');
$site=$this->request->get('site');
$rate=Typecho_Widget::widget('Widget_Options')->plugin('Meting')->bitrate;
$cookie=Typecho_Widget::widget('Widget_Options')->plugin('Meting')->cookie;

$cachekey="url/{$site}/{$id}/{$rate}";
$data=self::cacheRead($cachekey,60*15);
if(!$data){
$api=(new \Metowolf\Meting($site));
if($cookie!='')$api->cookie($cookie);
$data=$api->format(true)->url($id,$rate);
$data=json_decode($data,1);
self::cacheWrite($cachekey,$data);
if($type=='lrc'){
$data=$this->cacheRead($EID,60*60*24);
if(empty($data)){
$data=$api->lyric($id);
$this->cacheWrite($EID,$data);
}
$data=json_decode($data,true);
header("Content-Type: application/javascript");
echo $data['lyric'];
}
if(empty($data['url']))$data['url']="https://api.i-meto.com/Public/music/empty.mp3";
if($site=='netease'){
$data['url']=str_replace("http://","https://",$data['url']);
elseif($type=='pic'){
$data=$this->cacheRead($EID,60*60*24);
if(empty($data)){
$data=$api->pic($id,90);
$this->cacheWrite($EID,$data);
}
$data=json_decode($data,true);
$this->response->redirect($data['url']);
}
$this->response->redirect($data['url']);
}
elseif($type=='url'){
$data=$this->cacheRead($EID,60*15);
if(empty($data)){
$rate=Typecho_Widget::widget('Widget_Options')->plugin('Meting')->bitrate;
$cookie=Typecho_Widget::widget('Widget_Options')->plugin('Meting')->cookie;
if($server=='netease')$api->cookie($cookie);
$data=$api->url($id,$rate);
$this->cacheWrite($EID,$data);
}
$data=json_decode($data,true);
$url=$data['url'];

private function pic(){
if(!extension_loaded('Meting'))include_once 'include/Meting.php';
self::filterReferer();
$id=$this->request->get('id');
$site=$this->request->get('site');
$url=str_replace('http://m8','https://m8',$url);
$url=str_replace('http://m7','https://m8',$url);
$url=str_replace('http://m10','https://m10',$url);

$cachekey="pic/{$site}/{$id}";
$data=self::cacheRead($cachekey,60*60*24*30);
if(!$data){
$data=(new \Metowolf\Meting($site))->pic($id,90);
$data=json_decode($data,1);
self::cacheWrite($cachekey,$data);
if(empty($url))$url='https://api.i-meto.com/Public/music/empty.mp3';
$this->response->redirect($url);
}
$this->response->redirect($data['url']);
}

private function lrc(){
if(!extension_loaded('Meting'))include_once 'include/Meting.php';
self::filterReferer();
$id=$this->request->get('id');
$site=$this->request->get('site');

$cachekey="lyric/{$site}/{$id}";
$data=self::cacheRead($cachekey,60*60*24*10);
if(!$data){
$data=(new \Metowolf\Meting($site))->format(true)->lyric($id);
else{
$data=$this->cacheRead($EID,60*60*2);
if(empty($data)){
$data=$api->$type($id);
$this->cacheWrite($EID,$data);
}
$data=json_decode($data,1);
self::cacheWrite($cachekey,$data);
$url=Typecho_Common::url('action/metingapi',Helper::options()->index);

$music=array();
foreach($data as $vo){
$music[]=array(
'title' => $vo['name'],
'author' => implode(' / ',$vo['artist']),
'url' => $url.'?server='.$vo['source'].'&type=url&id='.$vo['url_id'].'&auth='.md5($salt.$vo['url_id'].$salt),
'pic' => $url.'?server='.$vo['source'].'&type=pic&id='.$vo['pic_id'].'&auth='.md5($salt.$vo['pic_id'].$salt),
'lrc' => $url.'?server='.$vo['source'].'&type=lrc&id='.$vo['lyric_id'].'&auth='.md5($salt.$vo['lyric_id'].$salt),
);
}
header("Content-Type: application/javascript");
echo json_encode($music);
}
if(!empty($data['tlyric']))$text=$this->lrctran($data['lyric'],$data['tlyric']);
else $text=$data['lyric'];
if(strlen($text)==0)$text='[00:00.00]无歌词';
echo $text;

}

private function lrctran($lyric,$tlyric){
preg_match_all('/\[(\d{2}:\d{2}\.\d+)\]([^\n]+)/i',$lyric,$t1);
preg_match_all('/\[(\d{2}:\d{2}\.\d+)\]([^\n]+)/i',$tlyric,$t2);
$from=$to=$t1[0];
$len1=sizeof($t1[0]);
$len2=sizeof($t2[0]);
for($i=0,$j=0;$i<$len1;$i++){
while($t1[1][$i]>$t2[1][$j]&&$j+1<$len2)$j++;
if($t1[1][$i]==$t2[1][$j]){
$t=trim(str_replace('/','',$t2[2][$j]));
if($t)$to[$i].=" (".$t2[2][$j].")";
$j++;
private function shortcode(){
$url=$this->request->get('data');
$url=trim($url);
if(empty($url))return;
$server='netease';$id='';$type='';
if(strpos($url,'163.com')!==false){
$server='netease';
if(preg_match('/playlist\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
elseif(preg_match('/toplist\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
elseif(preg_match('/album\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'album');
elseif(preg_match('/song\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'song');
elseif(preg_match('/artist\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
}
elseif(strpos($url,'qq.com')!==false){
$server='tencent';
if(preg_match('/playlist\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
elseif(preg_match('/album\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'album');
elseif(preg_match('/song\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'song');
elseif(preg_match('/singer\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'artist');
}
elseif(strpos($url,'xiami.com')!==false){
$server='xiami';
if(preg_match('/collect\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
elseif(preg_match('/album\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'album');
elseif(preg_match('/[\/.]\w+\/[songdem]+\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'song');
elseif(preg_match('/artist\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
if(!preg_match('/^\d*$/i',$id,$t)){
$data=self::curl($url);
preg_match('/'.$type.'\/(\d+)/i',$data,$id);
$id=$id[1];
}
}
return str_replace($from,$to,$lyric);
elseif(strpos($url,'kugou.com')!==false){
$server='kugou';
if(preg_match('/special\/single\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
elseif(preg_match('/song\/#hash\=(\w+)/i',$url,$id))list($id,$type)=array($id[1],'song');
elseif(preg_match('/album\/[single\/]*(\d+)/i',$url,$id))list($id,$type)=array($id[1],'album');
elseif(preg_match('/singer\/[home\/]*(\d+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
}
elseif(strpos($url,'baidu.com')!==false){
$server='baidu';
if(preg_match('/songlist\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
elseif(preg_match('/album\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'album');
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');
}
else{
echo "[Meting]\n[Music title=\"歌曲名\" author=\"歌手\" url=\"{$url}\"/]\n[/Meting]\n";
return;
}
echo "[Meting]\n[Music server=\"{$server}\" id=\"{$id}\" type=\"{$type}\"/]\n[/Meting]\n";
}

private function curl($url){
$curl=curl_init();
curl_setopt($curl,CURLOPT_URL,$url);
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,10);
curl_setopt($curl,CURLOPT_TIMEOUT,10);
curl_setopt($curl,CURLOPT_REFERER,$url);
$result=curl_exec($curl);
curl_close($curl);
return $result;
}

private function cacheWrite($k,$v){
if(!is_array($v)||is_null($v))return;
if(empty($v)||is_null($v))return;
$db=Typecho_Db::get();
$insert=$db->insert('table.metingv1')->rows(array('id'=>md5($k),'value'=>serialize($v),'last'=>time()));
$insert=$db->insert('table.metingv1')->rows(array('id'=>md5($k),'value'=>$v,'last'=>time()));
return $db->query($insert);
}

Expand All @@ -231,21 +186,19 @@ private function cacheRead($k,$t=3600){
$db->query($delete);
return false;
}
return unserialize($result['value']);
header("Meting-Cache: HIT");
return $result['value'];
}
else{
header("Meting-Cache: MISS");
return false;
}
else return false;
}

/*private function cacheFlush(){
$db=Typecho_Db::get();
$delete=$db->delete('table.metingv1')->where('last<?',time());
$db->query($delete);
}*/

private function filterReferer(){
if(isset($_SERVER['HTTP_REFERER'])&&strpos($_SERVER['HTTP_REFERER'],$_SERVER['HTTP_HOST'])===false){
http_response_code(403);
die();
die('[]');
}
}
}
Loading

0 comments on commit f120096

Please sign in to comment.