<?php
/**
* Meting music framework
* https://i-meto.com
* https://github.com/metowolf/Meting
* Version 1.5.2.
*
* Copyright 2018, METO Sheel <i@i-meto.com>
* Released under the MIT license
*/
namespace Metowolf;
class Meting
{
const VERSION = '1.5.2';
public $raw;
public $data;
public $info;
public $error;
public $status;
public $server;
public $format = false;
public $header = array(
'Accept' => '*/*',
'Accept-Encoding' => 'gzip, deflate',
'Accept-Language' => 'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4',
'Connection' => 'keep-alive',
'Content-Type' => 'application/x-www-form-urlencoded',
);
public function __construct($value = 'netease')
{
$this->site($value);
}
public function site($value)
{
$suppose = array('netease', 'tencent', 'xiami', 'kugou', 'baidu');
$this->server = in_array($value, $suppose) ? $value : 'netease';
$this->header = $this->curlset();
return $this;
}
public function cookie($value)
{
$this->header['Cookie'] = $value;
return $this;
}
public function format($value = true)
{
$this->format = $value;
return $this;
}
private function exec($api)
{
if (isset($api['encode'])) {
$api = call_user_func_array(array($this, $api['encode']), array($api));
}
if ($api['method'] == 'GET') {
if (isset($api['body'])) {
$api['url'] .= '?'.http_build_query($api['body']);
$api['body'] = null;
}
}
$this->curl($api['url'], $api['body']);
if (!$this->format) {
return $this->raw;
}
$this->data = $this->raw;
if (isset($api['decode'])) {
$this->data = call_user_func_array(array($this, $api['decode']), array($this->data));
}
if (isset($api['format'])) {
$this->data = $this->clean($this->data, $api['format']);
}
return $this->data;
}
private function curl($url, $payload = null, $headerOnly = 0)
{
$header = array_map(function ($k, $v) {
return $k.': '.$v;
}, array_keys($this->header), $this->header);
$curl = curl_init();
if (!is_null($payload)) {
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, is_array($payload) ? http_build_query($payload) : $payload);
}
curl_setopt($curl, CURLOPT_HEADER, $headerOnly);
curl_setopt($curl, CURLOPT_TIMEOUT, 20);
curl_setopt($curl, CURLOPT_ENCODING, 'gzip');
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, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
for ($i = 0; $i < 3; $i++) {
$this->raw = curl_exec($curl);
$this->info = curl_getinfo($curl);
$this->error = curl_errno($curl);
$this->status = $this->error ? curl_error($curl) : '';
if (!$this->error) {
break;
}
}
curl_close($curl);
return $this;
}
private function pickup($array, $rule)
{
$t = explode('.', $rule);
foreach ($t as $vo) {
if (!isset($array[$vo])) {
return array();
}
$array = $array[$vo];
}
return $array;
}
private function clean($raw, $rule)
{
$raw = json_decode($raw, true);
if (!empty($rule)) {
$raw = $this->pickup($raw, $rule);
}
if (!isset($raw[0]) && count($raw)) {
$raw = array($raw);
}
$result = array_map(array($this, 'format_'.$this->server), $raw);
return json_encode($result);
}
public function search($keyword, $option = null)
{
switch ($this->server) {
case 'netease':
$api = array(
'method' => 'POST',
'url' => 'http://music.163.com/api/cloudsearch/pc',
'body' => array(
's' => $keyword,
'type' => isset($option['type']) ? $option['type'] : 1,
'limit' => isset($option['limit']) ? $option['limit'] : 30,
'total' => 'true',
'offset' => isset($option['page']) && isset($option['limit']) ? ($option['page'] - 1) * $option['limit'] : 0,
),
'encode' => 'netease_AESCBC',
'format' => 'result.songs',
);
break;
case 'tencent':
$api = array(
'method' => 'GET',
'url' => 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp',
'body' => array(
'format' => 'json',
'p' => isset($option['page']) ? $option['page'] : 1,
'n' => isset($option['limit']) ? $option['limit'] : 30,
'w' => $keyword,
'aggr' => 1,
'lossless' => 1,
'cr' => 1,
'new_json' => 1,
),
'format' => 'data.song.list',
);
break;
case 'xiami':
$api = array(
'method' => 'GET',
'url' => 'http://h5api.m.xiami.com/h5/mtop.alimusic.search.searchservice.searchsongs/1.0/',
'body' => array(
'data' => array(
'key' => $keyword,
'pagingVO' => array(
'page' => isset($option['page']) ? $option['page'] : 1,
'pageSize' => isset($option['limit']) ? $option['limit'] : 30,
),
),
'r' => 'mtop.alimusic.search.searchservice.searchsongs',
),
'encode' => 'xiami_sign',
'format' => 'data.data.songs',
);
break;
case 'kugou':
$api = array(
'method' => 'GET',
'url' => 'http://ioscdn.kugou.com/api/v3/search/song',
'body' => array(
'iscorrect' => 1,
'pagesize' => isset($option['limit']) ? $option['limit'] : 30,
'plat' => 2,
'tag' => 1,
'sver' => 5,
'showtype' => 10,
'page' => isset($option['page']) ? $option['page'] : 1,
'keyword' => $keyword,
'version' => 8550,
),
'format' => 'data.info',
);
break;
case 'baidu':
$api = array(
'method' => 'GET',
'url' => 'https://gss2.baidu.com/6Ls1aze90MgYm2Gp8IqW0jdnxx1xbK/v1/restserver/ting',
'body' => array(
'from' => 'qianqianmini',
'method' => 'baidu.ting.search.merge',
'isNew' => 1,
'platform' => 'darwin',
'page_no' => isset($option['page']) ? $option['page'] : 1,
'query' => $keyword,
'version' => '11.0.2',
'page_size' => isset($option['limit']) ? $option['limit'] : 30,
),
'format' => 'result.song_info.song_list',
);
break;
}
return $this->exec($api);
}
public function song($id)
{
switch ($this->