Skip to content

Commit f120096

Browse files
committed
🔥 2.0.0, 架构重写,支持自定义歌曲
- 重写前端逻辑 - 支持自定义 API - 支持自定义歌曲 - 去除 jQuery 依赖 - 升级 Meting 库
1 parent 9ca611c commit f120096

File tree

6 files changed

+275
-296
lines changed

6 files changed

+275
-296
lines changed

Action.php

Lines changed: 148 additions & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -6,217 +6,172 @@ class Meting_Action extends Typecho_Widget implements Widget_Interface_Do {
66
public function execute(){}
77

88
public function action(){
9-
$this->on($this->request->is('do=musicjs'))->musicjs();
10-
$this->on($this->request->is('do=url'))->url();
11-
$this->on($this->request->is('do=pic'))->pic();
12-
$this->on($this->request->is('do=lrc'))->lrc();
139
$this->on($this->request->is('do=parse'))->shortcode();
10+
$this->on($this->request->isGet())->api();
1411
}
1512

16-
private function shortcode(){
17-
$urls=$this->request->get('data');
18-
$urls=explode("\n",$urls);
19-
echo "[Meting]\n";
20-
foreach($urls as $url){
21-
$url=trim($url);
22-
if($url=="")continue;
23-
$server='音乐平台';$id='编号';$type='类型';
24-
if(strpos($url,'163.com')!==false){
25-
$server='netease';
26-
if(preg_match('/playlist\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
27-
elseif(preg_match('/toplist\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
28-
elseif(preg_match('/album\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'album');
29-
elseif(preg_match('/song\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'song');
30-
elseif(preg_match('/artist\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
31-
}
32-
elseif(strpos($url,'qq.com')!==false){
33-
$server='tencent';
34-
if(preg_match('/playlist\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
35-
elseif(preg_match('/album\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'album');
36-
elseif(preg_match('/song\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'song');
37-
elseif(preg_match('/singer\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'artist');
38-
}
39-
elseif(strpos($url,'xiami.com')!==false){
40-
$server='xiami';
41-
if(preg_match('/collect\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
42-
elseif(preg_match('/album\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'album');
43-
elseif(preg_match('/[\/.]\w+\/[songdem]+\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'song');
44-
elseif(preg_match('/artist\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
45-
if(!preg_match('/^\d*$/i',$id,$t)){
46-
$data=self::curl($url);
47-
preg_match('/'.$type.'\/(\d+)/i',$data,$id);
48-
$id=$id[1];
49-
}
50-
}
51-
elseif(strpos($url,'kugou.com')!==false){
52-
$server='kugou';
53-
if(preg_match('/special\/single\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
54-
elseif(preg_match('/song\/#hash\=(\w+)/i',$url,$id))list($id,$type)=array($id[1],'song');
55-
elseif(preg_match('/album\/[single\/]*(\d+)/i',$url,$id))list($id,$type)=array($id[1],'album');
56-
elseif(preg_match('/singer\/[home\/]*(\d+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
57-
}
58-
elseif(strpos($url,'baidu.com')!==false){
59-
$server='baidu';
60-
if(preg_match('/songlist\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
61-
elseif(preg_match('/album\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'album');
62-
elseif(preg_match('/song\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'song');
63-
elseif(preg_match('/artist\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
64-
}
65-
else list($id,$type)=array($url,'search');
66-
echo '[Music server="'.$server.'" id="'.$id.'" type="'.$type.'"/]'."\n";
67-
}
68-
echo "[/Meting]";
13+
private function check($a,$b){
14+
if(!in_array($a,array('netease','tencent','baidu','xiami','kugou')))return false;
15+
if(!in_array($b,array('song','album','search','artist','playlist','lrc','url','pic')))return false;
16+
return true;
6917
}
7018

71-
private function curl($url){
72-
$curl=curl_init();
73-
curl_setopt($curl,CURLOPT_URL,$url);
74-
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
75-
curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,10);
76-
curl_setopt($curl,CURLOPT_TIMEOUT,10);
77-
curl_setopt($curl,CURLOPT_REFERER,$url);
78-
$result=curl_exec($curl);
79-
curl_close($curl);
80-
return $result;
81-
}
19+
private function api(){
20+
$this->filterReferer();
21+
$server=$this->request->get('server');
22+
$type=$this->request->get('type');
23+
$id=$this->request->get('id');
24+
25+
if(!$this->check($server,$type)||empty($id))die('[]');
8226

83-
private function musicjs(){
8427
if(!extension_loaded('Meting'))include_once 'include/Meting.php';
85-
self::filterReferer();
86-
$PID=$this->request->get('id');
87-
$data=$this->request->get('d');
88-
$data=json_decode(base64_decode($data),1);
89-
$setting=$this->request->get('s');
90-
$setting=json_decode(base64_decode($setting),1);
91-
$music=array();
92-
foreach($data as $vo){
93-
$EID=md5('js/'.$vo['server'].'/'.$vo['type'].'/'.$vo['id']);
94-
$t=self::cacheRead($EID,60*60*24*3);
95-
if(!$t){
96-
$API=(new \Metowolf\Meting($vo['server']))->format(true);
97-
$t=call_user_func_array(array($API,$vo['type']),array($vo['id']));
98-
$t=json_decode($t,1);
99-
self::cacheWrite($EID,$t);
28+
$api=new \Metowolf\Meting($server);
29+
$api->format(true);
30+
31+
$EID=md5($server.'/'.$type.'/'.$id);
32+
$salt=Typecho_Widget::widget('Widget_Options')->plugin('Meting')->salt;
33+
34+
if(in_array($type,array('lrc','pic','url'))){
35+
$auth1=md5($salt.$id.$salt);
36+
$auth2=$this->request->get('auth');
37+
if(strcmp($auth1,$auth2)){
38+
http_response_code(403);
39+
die();
10040
}
101-
$music=array_merge($music,$t);
10241
}
103-
$player=array(
104-
'theme' => isset($setting['theme'])?$setting['theme']:Typecho_Widget::widget('Widget_Options')->plugin('Meting')->theme?:'red',
105-
'preload' => isset($setting['preload'])?$setting['preload']:Typecho_Widget::widget('Widget_Options')->plugin('Meting')->preload?:'auto',
106-
'autoplay' => isset($setting['autoplay'])?$setting['autoplay']:Typecho_Widget::widget('Widget_Options')->plugin('Meting')->autoplay?:'false',
107-
'height' => isset($setting['height'])?$setting['height']:Typecho_Widget::widget('Widget_Options')->plugin('Meting')->height?:'340px',
108-
'mode' => isset($setting['mode'])?$setting['mode']:Typecho_Widget::widget('Widget_Options')->plugin('Meting')->mode?:'circulation',
109-
'music' => array(),
110-
);
111-
foreach($music as $vo){
112-
$URI=Typecho_Common::url('action/metingapi',Helper::options()->index);
113-
$player['music'][]=array(
114-
'title'=>$vo['name'],
115-
'author'=>implode(' / ',$vo['artist']),
116-
'url'=>$URI.'?site='.$vo['source'].'&do=url&id='.$vo['url_id'],
117-
'pic'=>$URI.'?site='.$vo['source'].'&do=pic&id='.$vo['pic_id'],
118-
'lrc'=>$URI.'?site='.$vo['source'].'&do=lrc&id='.$vo['lyric_id'],
119-
);
120-
}
121-
if(sizeof($player['music'])==1)$player['music']=$player['music'][0];
122-
$player['music']=json_encode($player['music']);
123-
124-
header('content-type:application/javascript');
125-
echo "
126-
var Meting{$PID} = new APlayer({
127-
element: document.getElementById('MetingPlayer'+{$PID}),
128-
autoplay: ".$player['autoplay'].",
129-
preload: \"".$player['preload']."\",
130-
showlrc: 3,
131-
mutex: true,
132-
mode: '".$player['mode']."',
133-
theme: \"".$player['theme']."\",
134-
music: ".$player['music'].",
135-
listmaxheight: '".$player['height']."',
136-
});
137-
";
138-
}
13942

140-
private function url(){
141-
if(!extension_loaded('Meting'))include_once 'include/Meting.php';
142-
self::filterReferer();
143-
$id=$this->request->get('id');
144-
$site=$this->request->get('site');
145-
$rate=Typecho_Widget::widget('Widget_Options')->plugin('Meting')->bitrate;
146-
$cookie=Typecho_Widget::widget('Widget_Options')->plugin('Meting')->cookie;
147-
148-
$cachekey="url/{$site}/{$id}/{$rate}";
149-
$data=self::cacheRead($cachekey,60*15);
150-
if(!$data){
151-
$api=(new \Metowolf\Meting($site));
152-
if($cookie!='')$api->cookie($cookie);
153-
$data=$api->format(true)->url($id,$rate);
154-
$data=json_decode($data,1);
155-
self::cacheWrite($cachekey,$data);
43+
if($type=='lrc'){
44+
$data=$this->cacheRead($EID,60*60*24);
45+
if(empty($data)){
46+
$data=$api->lyric($id);
47+
$this->cacheWrite($EID,$data);
48+
}
49+
$data=json_decode($data,true);
50+
header("Content-Type: application/javascript");
51+
echo $data['lyric'];
15652
}
157-
if(empty($data['url']))$data['url']="https://api.i-meto.com/Public/music/empty.mp3";
158-
if($site=='netease'){
159-
$data['url']=str_replace("http://","https://",$data['url']);
53+
elseif($type=='pic'){
54+
$data=$this->cacheRead($EID,60*60*24);
55+
if(empty($data)){
56+
$data=$api->pic($id,90);
57+
$this->cacheWrite($EID,$data);
58+
}
59+
$data=json_decode($data,true);
60+
$this->response->redirect($data['url']);
16061
}
161-
$this->response->redirect($data['url']);
162-
}
62+
elseif($type=='url'){
63+
$data=$this->cacheRead($EID,60*15);
64+
if(empty($data)){
65+
$rate=Typecho_Widget::widget('Widget_Options')->plugin('Meting')->bitrate;
66+
$cookie=Typecho_Widget::widget('Widget_Options')->plugin('Meting')->cookie;
67+
if($server=='netease')$api->cookie($cookie);
68+
$data=$api->url($id,$rate);
69+
$this->cacheWrite($EID,$data);
70+
}
71+
$data=json_decode($data,true);
72+
$url=$data['url'];
16373

164-
private function pic(){
165-
if(!extension_loaded('Meting'))include_once 'include/Meting.php';
166-
self::filterReferer();
167-
$id=$this->request->get('id');
168-
$site=$this->request->get('site');
74+
$url=str_replace('http://m8','https://m8',$url);
75+
$url=str_replace('http://m7','https://m8',$url);
76+
$url=str_replace('http://m10','https://m10',$url);
16977

170-
$cachekey="pic/{$site}/{$id}";
171-
$data=self::cacheRead($cachekey,60*60*24*30);
172-
if(!$data){
173-
$data=(new \Metowolf\Meting($site))->pic($id,90);
174-
$data=json_decode($data,1);
175-
self::cacheWrite($cachekey,$data);
78+
if(empty($url))$url='https://api.i-meto.com/Public/music/empty.mp3';
79+
$this->response->redirect($url);
17680
}
177-
$this->response->redirect($data['url']);
178-
}
179-
180-
private function lrc(){
181-
if(!extension_loaded('Meting'))include_once 'include/Meting.php';
182-
self::filterReferer();
183-
$id=$this->request->get('id');
184-
$site=$this->request->get('site');
185-
186-
$cachekey="lyric/{$site}/{$id}";
187-
$data=self::cacheRead($cachekey,60*60*24*10);
188-
if(!$data){
189-
$data=(new \Metowolf\Meting($site))->format(true)->lyric($id);
81+
else{
82+
$data=$this->cacheRead($EID,60*60*2);
83+
if(empty($data)){
84+
$data=$api->$type($id);
85+
$this->cacheWrite($EID,$data);
86+
}
19087
$data=json_decode($data,1);
191-
self::cacheWrite($cachekey,$data);
88+
$url=Typecho_Common::url('action/metingapi',Helper::options()->index);
89+
90+
$music=array();
91+
foreach($data as $vo){
92+
$music[]=array(
93+
'title' => $vo['name'],
94+
'author' => implode(' / ',$vo['artist']),
95+
'url' => $url.'?server='.$vo['source'].'&type=url&id='.$vo['url_id'].'&auth='.md5($salt.$vo['url_id'].$salt),
96+
'pic' => $url.'?server='.$vo['source'].'&type=pic&id='.$vo['pic_id'].'&auth='.md5($salt.$vo['pic_id'].$salt),
97+
'lrc' => $url.'?server='.$vo['source'].'&type=lrc&id='.$vo['lyric_id'].'&auth='.md5($salt.$vo['lyric_id'].$salt),
98+
);
99+
}
100+
header("Content-Type: application/javascript");
101+
echo json_encode($music);
192102
}
193-
if(!empty($data['tlyric']))$text=$this->lrctran($data['lyric'],$data['tlyric']);
194-
else $text=$data['lyric'];
195-
if(strlen($text)==0)$text='[00:00.00]无歌词';
196-
echo $text;
103+
197104
}
198105

199-
private function lrctran($lyric,$tlyric){
200-
preg_match_all('/\[(\d{2}:\d{2}\.\d+)\]([^\n]+)/i',$lyric,$t1);
201-
preg_match_all('/\[(\d{2}:\d{2}\.\d+)\]([^\n]+)/i',$tlyric,$t2);
202-
$from=$to=$t1[0];
203-
$len1=sizeof($t1[0]);
204-
$len2=sizeof($t2[0]);
205-
for($i=0,$j=0;$i<$len1;$i++){
206-
while($t1[1][$i]>$t2[1][$j]&&$j+1<$len2)$j++;
207-
if($t1[1][$i]==$t2[1][$j]){
208-
$t=trim(str_replace('/','',$t2[2][$j]));
209-
if($t)$to[$i].=" (".$t2[2][$j].")";
210-
$j++;
106+
private function shortcode(){
107+
$url=$this->request->get('data');
108+
$url=trim($url);
109+
if(empty($url))return;
110+
$server='netease';$id='';$type='';
111+
if(strpos($url,'163.com')!==false){
112+
$server='netease';
113+
if(preg_match('/playlist\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
114+
elseif(preg_match('/toplist\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
115+
elseif(preg_match('/album\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'album');
116+
elseif(preg_match('/song\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'song');
117+
elseif(preg_match('/artist\?id=(\d+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
118+
}
119+
elseif(strpos($url,'qq.com')!==false){
120+
$server='tencent';
121+
if(preg_match('/playlist\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
122+
elseif(preg_match('/album\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'album');
123+
elseif(preg_match('/song\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'song');
124+
elseif(preg_match('/singer\/([^\.]*)/i',$url,$id))list($id,$type)=array($id[1],'artist');
125+
}
126+
elseif(strpos($url,'xiami.com')!==false){
127+
$server='xiami';
128+
if(preg_match('/collect\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
129+
elseif(preg_match('/album\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'album');
130+
elseif(preg_match('/[\/.]\w+\/[songdem]+\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'song');
131+
elseif(preg_match('/artist\/(\w+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
132+
if(!preg_match('/^\d*$/i',$id,$t)){
133+
$data=self::curl($url);
134+
preg_match('/'.$type.'\/(\d+)/i',$data,$id);
135+
$id=$id[1];
211136
}
212137
}
213-
return str_replace($from,$to,$lyric);
138+
elseif(strpos($url,'kugou.com')!==false){
139+
$server='kugou';
140+
if(preg_match('/special\/single\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
141+
elseif(preg_match('/song\/#hash\=(\w+)/i',$url,$id))list($id,$type)=array($id[1],'song');
142+
elseif(preg_match('/album\/[single\/]*(\d+)/i',$url,$id))list($id,$type)=array($id[1],'album');
143+
elseif(preg_match('/singer\/[home\/]*(\d+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
144+
}
145+
elseif(strpos($url,'baidu.com')!==false){
146+
$server='baidu';
147+
if(preg_match('/songlist\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'playlist');
148+
elseif(preg_match('/album\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'album');
149+
elseif(preg_match('/song\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'song');
150+
elseif(preg_match('/artist\/(\d+)/i',$url,$id))list($id,$type)=array($id[1],'artist');
151+
}
152+
else{
153+
echo "[Meting]\n[Music title=\"歌曲名\" author=\"歌手\" url=\"{$url}\"/]\n[/Meting]\n";
154+
return;
155+
}
156+
echo "[Meting]\n[Music server=\"{$server}\" id=\"{$id}\" type=\"{$type}\"/]\n[/Meting]\n";
157+
}
158+
159+
private function curl($url){
160+
$curl=curl_init();
161+
curl_setopt($curl,CURLOPT_URL,$url);
162+
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
163+
curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,10);
164+
curl_setopt($curl,CURLOPT_TIMEOUT,10);
165+
curl_setopt($curl,CURLOPT_REFERER,$url);
166+
$result=curl_exec($curl);
167+
curl_close($curl);
168+
return $result;
214169
}
215170

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

@@ -231,21 +186,19 @@ private function cacheRead($k,$t=3600){
231186
$db->query($delete);
232187
return false;
233188
}
234-
return unserialize($result['value']);
189+
header("Meting-Cache: HIT");
190+
return $result['value'];
191+
}
192+
else{
193+
header("Meting-Cache: MISS");
194+
return false;
235195
}
236-
else return false;
237196
}
238197

239-
/*private function cacheFlush(){
240-
$db=Typecho_Db::get();
241-
$delete=$db->delete('table.metingv1')->where('last<?',time());
242-
$db->query($delete);
243-
}*/
244-
245198
private function filterReferer(){
246199
if(isset($_SERVER['HTTP_REFERER'])&&strpos($_SERVER['HTTP_REFERER'],$_SERVER['HTTP_HOST'])===false){
247200
http_response_code(403);
248-
die();
201+
die('[]');
249202
}
250203
}
251204
}

0 commit comments

Comments
 (0)