From 2f56858b5523b7eab989d0b65c7cf505f7fa0471 Mon Sep 17 00:00:00 2001 From: "cn.yimian.xyz" Date: Sun, 14 Jun 2020 11:59:27 +0800 Subject: [PATCH] work --- composer.json | 5 + composer.lock | 68 ++ functions.php | 582 ++++++++++ index.php | 142 +++ intro.html | 58 + vendor/autoload.php | 7 + vendor/composer/ClassLoader.php | 445 ++++++++ vendor/composer/LICENSE | 21 + vendor/composer/autoload_classmap.php | 9 + vendor/composer/autoload_namespaces.php | 9 + vendor/composer/autoload_psr4.php | 10 + vendor/composer/autoload_real.php | 52 + vendor/composer/autoload_static.php | 31 + vendor/composer/installed.json | 54 + vendor/metowolf/meting/.editorconfig | 24 + vendor/metowolf/meting/.gitignore | 3 + vendor/metowolf/meting/.travis.yml | 28 + vendor/metowolf/meting/LICENSE | 21 + vendor/metowolf/meting/README.md | 92 ++ vendor/metowolf/meting/composer.json | 38 + vendor/metowolf/meting/src/Meting.php | 1365 +++++++++++++++++++++++ 21 files changed, 3064 insertions(+) create mode 100644 composer.json create mode 100644 composer.lock create mode 100755 functions.php create mode 100644 index.php create mode 100644 intro.html create mode 100644 vendor/autoload.php create mode 100644 vendor/composer/ClassLoader.php create mode 100644 vendor/composer/LICENSE create mode 100644 vendor/composer/autoload_classmap.php create mode 100644 vendor/composer/autoload_namespaces.php create mode 100644 vendor/composer/autoload_psr4.php create mode 100644 vendor/composer/autoload_real.php create mode 100644 vendor/composer/autoload_static.php create mode 100644 vendor/composer/installed.json create mode 100644 vendor/metowolf/meting/.editorconfig create mode 100644 vendor/metowolf/meting/.gitignore create mode 100644 vendor/metowolf/meting/.travis.yml create mode 100644 vendor/metowolf/meting/LICENSE create mode 100644 vendor/metowolf/meting/README.md create mode 100644 vendor/metowolf/meting/composer.json create mode 100644 vendor/metowolf/meting/src/Meting.php diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..59ac60a --- /dev/null +++ b/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "metowolf/meting": "^1.5" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..4b97f9d --- /dev/null +++ b/composer.lock @@ -0,0 +1,68 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "70ff81c59564e9617fed0bf28f62fad1", + "packages": [ + { + "name": "metowolf/meting", + "version": "v1.5.7", + "source": { + "type": "git", + "url": "https://github.com/metowolf/Meting.git", + "reference": "54178aa112da5db09f487d862d7ae62cbf7bc060" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/metowolf/Meting/zipball/54178aa112da5db09f487d862d7ae62cbf7bc060", + "reference": "54178aa112da5db09f487d862d7ae62cbf7bc060", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-openssl": "*", + "php": ">=5.4.0" + }, + "suggest": { + "ext-bcmath": "Required to use BC Math calculate RSA.", + "ext-openssl": "Required to use OpenSSL encrypt params." + }, + "type": "library", + "autoload": { + "psr-4": { + "Metowolf\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "metowolf", + "email": "i@i-meto.com", + "homepage": "https://i-meto.com" + } + ], + "description": "A powerful music API framework to accelerate development.", + "homepage": "https://github.com/metowolf/Meting", + "keywords": [ + "lightweight", + "lighty", + "music api", + "php music" + ], + "time": "2019-06-16T05:55:00+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/functions.php b/functions.php new file mode 100755 index 0000000..4247878 --- /dev/null +++ b/functions.php @@ -0,0 +1,582 @@ +connect_error) + { + die("Mysql Connect Failed: " . $conn->connect_error); + } + + return ($conn); +} + +//get table row number::(data_cnnct var,table name) ::(row number) +function db__rowNum($conn,$table,$clmnName="",$value="",$clmnName2="",$value2="") +{ + + $table=db__antisql($table); + $clmnName=db__antisql($clmnName); + $value=db__antisql($value); + $clmnName2=db__antisql($clmnName2); + $value2=db__antisql($value2); + + + if($clmnName=="") $sql = "SELECT COUNT(*) FROM $table"; + elseif($clmnName2=="") $sql = "SELECT COUNT(*) FROM $table where $clmnName='$value'"; + else $sql = "SELECT COUNT(*) FROM $table where $clmnName='$value' AND $clmnName2='$value2'"; + + $row_count = $conn->query($sql); + list($row_num) = $row_count->fetch_row(); + return ($row_num); +} + +//get row data from database::(data_cnnct var, table name,column name, column value)::(row info) +function db__getData($conn,$table,$clmnName="",$value="",$clmnName2="",$value2="") +{ + + $table=db__antisql($table); + $clmnName=db__antisql($clmnName); + $value=db__antisql($value); + $clmnName2=db__antisql($clmnName2); + $value2=db__antisql($value2); + + + if($clmnName=="") $sql = "SELECT * FROM $table"; + elseif($clmnName2=="") $sql = "SELECT * FROM $table where $clmnName='$value'"; + else $sql = "SELECT * FROM $table where $clmnName='$value' AND $clmnName2='$value2'"; + + $result = $conn->query($sql); + //no data + if ($result->num_rows > 0) {}else{return 404;} + + $i=0; + $arr=array(); + while($row = $result->fetch_assoc()) { + $arr[$i++]=$row; + } + return ($arr); +} + + +//fnct for insert a row to database +function db__insertData($conn,$table,$content) +{ + $table=db__antisql($table); + + $key=array_keys($content); + + $key=db__antisql($key); + + $sql="insert INTO $table ("; + + for($i=0;$iquery($sql) === TRUE)) echo "SQL Insert Error: " . $sql . "
" . $conn->error; + +} + + +//fnct for update a row to database without check +function db__updateData($conn,$table,$content,$index) +{ + $key=array_keys($content); + $key=db__antisql($key); + + $sql="UPDATE $table SET "; + + for($i=0;$iquery($sql) === TRUE)) echo "SQL Insert Error: " . $sql . "
" . $conn->error; + +} + + + + +//push row data from database::(data_cnnct var, table name,column name, column value)::(row info) +function db__pushData($conn,$table,$content,$index="",$is_force=1) +{ + if($index) + { + $index_keys=array_keys($index); + + if(count($index_keys)==1) $result=db__rowNum($conn,$table,$index_keys[0],$index[$index_keys[0]]); + + elseif(count($index_keys)==2) $result=db__rowNum($conn,$table,$index_keys[0],$index[$index_keys[0]],$index_keys[1],$index[$index_keys[1]]); + + else return -1; + + if($result>0) db__updateData($conn,$table,$content,$index); + else if($is_force) db__insertData($conn,$table,$content); + + } + else + db__insertData($conn,$table,$content); +} + + +function db__delData($conn, $table, $clmnName, $value) +{ + $value=db__antisql($value); + $clmnName=db__antisql($clmnName); + + $sql = "DELETE FROM $table WHERE $clmnName = '$value'"; + $conn->query($sql); +} + + +//anti sql +function db__antisql($str) +{ + return(str_ireplace("'","",$str)); +} + + +/*****log******/ +function yimian__log($table, $val, $index = "", $cnt = null){ + + if(!isset($cnt)) $cnt = db__connect("log"); + if($index != "") db__pushData($cnt, $table, $val, $index); + else db__pushData($cnt, $table, $val); +} + +/** get from address **/ +function get_from(){ + + if($_SERVER['HTTP_REFERER']) return $_SERVER['HTTP_REFERER']; + elseif($_REQUEST['from']) return $_REQUEST['from']; +} + +function get_from_domain(){ + + $str = str_replace("http://","",get_from()); + $str = str_replace("https://","",$str); + $strdomain = explode("/",$str); + return $strdomain[0]; +} + + +/*****curl*****/ + +function curl__post($url = '', $param) { + + if(empty($url)) { + return false; + } + + $o = ""; + foreach ($param as $k => $v) { + $o .= "$k=".urlencode($v)."&" ; + } + + $postUrl = $url; + $curlPost = substr($o,0,-1); + $ch = curl_init();//初始化curl + curl_setopt($ch, CURLOPT_URL,$postUrl);//抓取指定网页 + curl_setopt($ch, CURLOPT_HEADER, 0);//设置header + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上 + curl_setopt($ch, CURLOPT_POST, 1);//post提交方式 + curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost); + $data = curl_exec($ch);//运行curl + curl_close($ch); + + return $data; +} + + + +/* get IP */ +function get_ip(){ + return getIp(); +} +function getIp() +{ + if (isset($_SERVER)) { + if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { + $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); + + foreach ($arr as $ip) { + $ip = trim($ip); + + if ($ip != 'unknown') { + $realip = $ip; + break; + } + } + } else if (isset($_SERVER['HTTP_CLIENT_IP'])) { + $realip = $_SERVER['HTTP_CLIENT_IP']; + } else if (isset($_SERVER['REMOTE_ADDR'])) { + $realip = $_SERVER['REMOTE_ADDR']; + } else { + $realip = '0.0.0.0'; + } + } else if (getenv('HTTP_X_FORWARDED_FOR')) { + $realip = getenv('HTTP_X_FORWARDED_FOR'); + } else if (getenv('HTTP_CLIENT_IP')) { + $realip = getenv('HTTP_CLIENT_IP'); + } else { + $realip = getenv('REMOTE_ADDR'); + } + + preg_match('/[\\d\\.]{7,15}/', $realip, $onlineip); + $realip = (!empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0'); + return $realip; +} + + +/* obs get video */ +function getVideo($path, $time = 120*60){ + + return trim(exec(__DIR__."/obsutil sign obs://yimian-video/". $path ." -e=". $time)); +} + + +/* obs get img */ +function getImg($path, $time = 300){ + + return str_replace('yimian-image.obs.cn-east-2.myhuaweicloud.com:443','image.yimian.xyz',trim(exec(__DIR__."/obsutil sign obs://yimian-image/". $path ." -e=". $time))); +} + +function getImgsInfo($type){ + $arr_os = array(); + $arr = array(); + ini_set("pcre.backtrack_limit" , -1); ini_set("pcre.recursion_limit" , -1); ini_set("memory_limit" , "1024M"); + exec(__DIR__.'/obsutil ls obs://yimian-image/'.$type.' -limit=-1', $arr_os); + //exec(__DIR__.'/obsutil', $arr_os); + //var_dump($arr_os); + //echo count($arr_os); + + $str = implode ($arr_os); + preg_match_all('/img_(\S*?)_(\d{2,4})x(\d{2,4})_(\S*?)_(\S*?)_(\S*?).(jpe?g|png|gif|svg)\b/', $str, $arr); + + return $arr; +} + + + +/*****gugu*****/ + +function yimian__gugu($body){ + + $body = iconv("UTF-8","gbk//TRANSLIT",$body); + $url = "http://open.memobird.cn/home/printpaper"; + return curl__post($url, array("ak" => $GLOBALS['ggj_ak'], "userID" => $GLOBALS['ggj_userID'], "memobirdID" => $GLOBALS['ggj_memobirdID'], "printcontent" => "T:".base64_encode($body)."", "timestamp" => "".time()."")); +} + + +function gugu__send($ak, $userID, $memobirdID, $body){ + + $body = iconv("UTF-8","gbk//TRANSLIT",$body); + $url = "http://open.memobird.cn/home/printpaper"; + return curl__post($url, array("ak" => $ak, "userID" => $userID, "memobirdID" => $memobirdID, "printcontent" => "T:".base64_encode($body)."", "timestamp" => "".time()."")); +} + + + +/** function for mail **/ + +function yimian__mail($to, $subject, $body, $from){ + + + if($from == "") $from = "IoTcat 呓喵酱"; + if($body == "") $body = "额(⊙﹏⊙) 未找到指定的邮件内容耶( •̀ ω •́ )y

更多信息请咨询IoTcat期待你的回应啦~"; + if($subject == "") $subject = "来自IoTcat的一声问候~"; + + $data = array( + 'fromName' => $from, // 发件人名称 + 'from' => "admin@iotcat.xyz", // 发件地址 + 'to' => $to, // 收件地址 + 'replyTo' => "i@iotcat.me", // 回信地址 + 'subject' => $subject, + 'html' => $body + ); + + // 当前请求区域 + // 杭州 + // API地址 + $data['api'] = 'https://dm.aliyuncs.com/'; + // API版本号 + $data['version'] = '2015-11-23'; + // 机房信息 + $data['region'] = 'cn-hangzhou'; + + // AccessKeyId + $data['accessid'] = $GLOBALS['aym_AccessKey']; + // AccessKeySecret + $data['accesssecret'] = $GLOBALS['aym_SecretKey']; + // 是否成功 + return aliyun($data); + +} + + + +//mail alliyun api +function aliyun($param) +{ + // 重新组合为阿里云所使用的参数 + $data = array( + 'Action' => 'SingleSendMail', // 操作接口名 + 'AccountName' => $param['from'], // 发件地址 + 'ReplyToAddress' => "true", // 回信地址 + 'AddressType' => 1, // 地址类型 + 'ToAddress' => $param['to'], // 收件地址 + 'FromAlias' => $param['fromName'], // 发件人名称 + 'Subject' => $param['subject'], // 邮件标题 + 'HtmlBody' => $param['html'], // 邮件内容 + 'Format' => 'JSON', // 返回JSON + 'Version' => $param['version'], // API版本号 + 'AccessKeyId' => $param['accessid'], // Access Key ID + 'SignatureMethod' => 'HMAC-SHA1', // 签名方式 + 'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'), // 请求时间 + 'SignatureVersion' => '1.0', // 签名算法版本 + 'SignatureNonce' => md5(time()), // 唯一随机数 + 'RegionId' => $param['region'] // 机房信息 + ); + // 请求签名 + $data['Signature'] = sign($data, $param['accesssecret']); + // 初始化Curl + $ch = curl_init(); + // 设置为POST请求 + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); + // 请求地址 + curl_setopt($ch, CURLOPT_URL, $param['api']); + // 返回数据 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); + // 提交参数 + curl_setopt($ch, CURLOPT_POSTFIELDS, getPostHttpBody($data)); + // 关闭ssl验证 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); + // 执行请求 + $result = curl_exec($ch); + // 获取错误代码 + $errno = curl_errno($ch); + // 获取错误信息 + $error = curl_error($ch); + // 获取返回状态码 + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + // 关闭请求 + curl_close($ch); + // 成功标识 + $flag = TRUE; + // 如果开启了Debug + if (1) { + // 记录时间 + $log = '[Aliyun] ' . date('Y-m-d H:i:s') . ': ' . PHP_EOL; + // 如果失败 + if ( $errno ) { + // 设置失败 + $flag = FALSE; + $log .= '邮件发送失败, 错误代码:' . $errno . ',错误提示: ' . $error . PHP_EOL; + } + // 如果失败 + if ( 400 <= $httpCode ) { + // 设置失败 + $flag = FALSE; + // 尝试转换json + if ( $json = json_decode($result) ) { + $log .= '邮件发送失败,错误代码:' . $json->Code . ',错误提示:' . $json->Message . PHP_EOL; + } else { + $log .= '邮件发送失败, 请求返回HTTP Code:' . $httpCode . PHP_EOL; + } + } + // 记录返回值 + $log .= '邮件发送返回数据:' . serialize($result) . PHP_EOL; + // 写入文件 + } + yimian__log("log_mail",array("timestamp" => date('Y-m-d H:i:s', time()), "to_" => $param['to'], "from_" => $param['fromName'], "subject" => $param['subject'], "body" => $param['html'], "success" => (($flag)?1:0), "return_" => $log)); + // 返回结果 + //echo $log; + return $flag; +} + + +/** + * 阿里云签名 + * + * @static + * @access private + * + * @param array $param 签名参数 + * @param string $accesssecret 秘钥 + * + * @return string + */ +function sign($param, $accesssecret) +{ + // 参数排序 + ksort($param); + // 组合基础 + $stringToSign = 'POST&' . percentEncode('/') . '&'; + // 临时变量 + $tmp = ''; + // 循环参数列表 + foreach ( $param as $k => $v ) { + // 组合参数 + $tmp .= '&' . percentEncode($k) . '=' . percentEncode($v); + } + // 去除最后一个& + $tmp = trim($tmp, '&'); + // 组合签名参数 + $stringToSign = $stringToSign . percentEncode($tmp); + // 数据签名 + $signature = base64_encode(hash_hmac('sha1', $stringToSign, $accesssecret . '&', TRUE)); + // 返回签名 + return $signature; +} + +/** + * 阿里云签名编码转换 + * + * @static + * @access private + * + * @param string $val 要转换的编码 + * + * @return string|string[]|null + */ +function percentEncode($val) +{ + // URL编码 + $res = urlencode($val); + // 加号转换为%20 + $res = preg_replace('/\+/', '%20', $res); + // 星号转换为%2A + $res = preg_replace('/\*/', '%2A', $res); + // %7E转换为~ + $res = preg_replace('/%7E/', '~', $res); + return $res; +} + +/** + * 阿里云请求参数组合 + * + * @static + * @access private + * + * @param array $param 发送参数 + * + * @return bool|string + */ +function getPostHttpBody($param) +{ + // 空字符串 + $str = ""; + // 循环参数 + foreach ( $param as $k => $v ) { + // 组合参数 + $str .= $k . '=' . urlencode($v) . '&'; + } + // 去除第一个& + return substr($str, 0, -1); +} + + +/* sms */ +require __DIR__ . "/../../../lib/qcloudsms/src/index.php"; + +use Qcloud\Sms\SmsSingleSender; +use Qcloud\Sms\SmsMultiSender; +use Qcloud\Sms\SmsVoiceVerifyCodeSender; +use Qcloud\Sms\SmsVoicePromptSender; +use Qcloud\Sms\SmsStatusPuller; +use Qcloud\Sms\SmsMobileStatusPuller; + +use Qcloud\Sms\VoiceFileUploader; +use Qcloud\Sms\FileVoiceSender; +use Qcloud\Sms\TtsVoiceSender; + + +function yimian__sms($to, $tpl, $msg1, $msg2, $msg3){ + + $msg = array(); + if($tpl == 3) array_push($msg, $msg1, $msg2, $msg3); + else array_push($msg, $msg1, $msg2); + + $appid = $GLOBALS['sms_appid']; + + $appkey = $GLOBALS['sms_appkey']; + + $smsSign = $GLOBALS['sms_smsSign']; + + if($tpl == 1) $templateId = 287129; /*由于{1},本站{2}。给您带来不便深表歉意!*/ + if($tpl == 2) $templateId = 300726; /*您好!您收到一条来自{1}的消息,内容是{2}。感谢您使用本站的服务!*/ + if($tpl == 3) $templateId = 205311; /*您{1}的{2}为{3},请于5分钟内填写。如非本人操作,请忽略本短信。祝好!*/ + if($tpl == 4) $templateId = 244004; /*{1}已解决,本站{2}服务已恢复!给您带来不便深表歉意!特此告知!*/ + if($tpl == 5) $templateId = 300722; /*你好呀,你收到了一条来自访客{1}的评论,内容是{2}。感谢你使用本站的服务啦 ~*/ + + try { + $ssender = new SmsSingleSender($appid, $appkey); + $params = $msg; + $result = $ssender->sendWithParam("86", $to, $templateId, + $params, $smsSign, "", ""); /* 签名参数未提供或者为空时,会使用默认签名发送短信*/ + $rsp = json_decode($result); + echo $result; + } catch(\Exception $e) { + echo var_dump($e); + } + +} + diff --git a/index.php b/index.php new file mode 100644 index 0000000..235c762 --- /dev/null +++ b/index.php @@ -0,0 +1,142 @@ +500, "err"=>"You need to provide an id!!")); + die(); + } + $res = get_object_vars(json_decode($API->format(true)->url($id, 320))); + if(in_array("url", $res)){ + echo json_encode(array("code"=>404, "err"=>"No Found!!")); + die(); + } + $res['url'] = str_replace("http", "https", $res['url']); + log_api(); + header("Location: ".$res['url']); + die(); +} + + +if($type == "cover"){ + if(!isset($id)){ + echo json_encode(array("code"=>500, "err"=>"You need to provide an id!!")); + die(); + } + $res = get_object_vars(json_decode($API->format(true)->pic($id))); + if(in_array("url", $res)){ + echo json_encode(array("code"=>404, "err"=>"No Found!!")); + die(); + } + log_api(); + header("Location: ".$res["url"]); + die(); +} + + + +if($type == "lrc"){ + if(!isset($id)){ + echo json_encode(array("code"=>500, "err"=>"You need to provide an id!!")); + die(); + } + $res = get_object_vars(json_decode($API->format(true)->lyric($id))); + if(in_array("lyric", $res)){ + echo json_encode(array("code"=>404, "err"=>"No Found!!")); + die(); + } + log_api(); + header("Content-Type: text/plain;charset=utf-8"); + echo $res["lyric"]; + die(); +} + + + + + +if($type == "single"){ + if(!isset($id)){ + echo json_encode(array("code"=>500, "err"=>"You need to provide an id!!")); + die(); + } + $content = get_object_vars(getSongInfo($id, $API)[0]); + //var_dump($content); + $o = array("id"=>$content["id"], "name"=>$content["name"], "artist"=>$content["artist"][0], "album"=>$content["album"], "url"=>"https://api.yimian.xyz/msc/?type=url&id=".$content["url_id"], "cover"=>"https://api.yimian.xyz/msc/?type=cover&id=".$content["pic_id"], "lrc"=>"https://api.yimian.xyz/msc/?type=lrc&id=".$content["lyric_id"]); + if(!$o){ + echo json_encode(array("code"=>404, "err"=>"Cannot find any songs!!")); + die(); + } + echo json_encode($o); + log_api(); + die(); +} + + +if($type == "playlist"){ + /* 7.18 events */ + //$id="2889727316"; + if(!isset($id)){ + echo json_encode(array("code"=>500, "err"=>"You need to provide an id!!")); + die(); + } + $content = array(); + $o = array(); + + foreach (getPlaylistInfo($id, $API) as $key => $value) { + $content = get_object_vars($value); + array_push($o, array("id"=>$content["id"], "name"=>$content["name"], "artist"=>$content["artist"][0], "album"=>$content["album"], "url"=>"https://api.yimian.xyz/msc/?type=url&id=".$content["url_id"], "cover"=>"https://api.yimian.xyz/msc/?type=cover&id=".$content["pic_id"], "lrc"=>"https://api.yimian.xyz/msc/?type=lrc&id=".$content["lyric_id"])); + } + if(!$o){ + echo json_encode(array("code"=>404, "err"=>"Cannot find any songs!!")); + die(); + } + if($random) shuffle($o); + if($limit) $o = array_slice($o, 0, $limit); + echo json_encode($o); + log_api(); + die(); +} + + +echo json_encode(array("code"=>500, "err"=>"Cannot find such type!!")); + + + +function getSongInfo($id, $API){ + return json_decode($API->format(true)->song($id)); +} + +function getPlaylistInfo($id, $API){ + return json_decode($API->format(true)->playlist($id)); +} + + + +function log_api(){ + yimian__log("log_api", array("api" => "msc", "timestamp" => date('Y-m-d H:i:s', time()), "ip" => ip2long(getIp()), "_from" => get_from(), "content" => $_SERVER["QUERY_STRING"])); + return; +} diff --git a/intro.html b/intro.html new file mode 100644 index 0000000..dceb48e --- /dev/null +++ b/intro.html @@ -0,0 +1,58 @@ + + + + + + 音乐获取 API + + + + + + + +
+
+

音乐获取 - API

+
+

# 音乐获取API请求方式 # +
    +
  • Method: GET/POST
+
# 请求地址 # +
+ https://api.yimian.xyz/msc +
# 参数 # 【目前仅支持网易云音乐】 +
+
  • type (必填)//type=single单曲信息/playlist歌单歌曲信息/url获取歌曲/cover获取封面/lrc获取歌词
  • +
  • id (必填,搭配type使用) //id=198401123
  • +
  • random //random=true 仅对playlist有效,返回的歌曲是否打乱顺序,默认false
  • +
  • limit //limit=10 返回歌单最大长度
  • +
    + # 返回数据(Json格式) #

    +
  • single模式: {id: "歌曲id", name: "歌曲名称", artist: "第一作者", album: "专辑名称", url: "单曲地址", cover: "封面地址", lrc: "歌词地址"}

  • +
  • playlist模式: [{id: "歌曲id", name: "歌曲名称", artist: "第一作者", album: "专辑名称", url: "单曲地址", cover: "封面地址", lrc: "歌词地址"}, {歌曲2..}, {歌曲3..}]

  • +
  • 错误: {code: 500, err: "错误信息"}
  • +
    # 备注 # +
    更多用法参考 + https://www.eee.dog/tech/rand-pic-api.html +
    +
    # 示例 # +
    + https://api.yimian.xyz/msc/?type=single&id=36308263 +
    + https://api.yimian.xyz/msc/?type=playlist&id=808097971 +
    + https://api.yimian.xyz/msc/?type=playlist&id=808097971&limit=14 +
    + https://api.yimian.xyz/msc/?type=playlist&id=808097971&limit=14&random=true +
    + https://api.yimian.xyz/msc/?type=url&id=36308263 +
    + https://api.yimian.xyz/msc/?type=cover&id=3384296792803059 +
    + https://api.yimian.xyz/msc/?type=lrc&id=36308263

    +
    +
    + + + diff --git a/vendor/autoload.php b/vendor/autoload.php new file mode 100644 index 0000000..9c1e342 --- /dev/null +++ b/vendor/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + private $classMapAuthoritative = false; + private $missingClasses = array(); + private $apcuPrefix; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..7a91153 --- /dev/null +++ b/vendor/composer/autoload_classmap.php @@ -0,0 +1,9 @@ + array($vendorDir . '/metowolf/meting/src'), +); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php new file mode 100644 index 0000000..40016f8 --- /dev/null +++ b/vendor/composer/autoload_real.php @@ -0,0 +1,52 @@ += 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInit7bd602fdce79cdf3c88e3cdb52a761f5::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + return $loader; + } +} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php new file mode 100644 index 0000000..817c506 --- /dev/null +++ b/vendor/composer/autoload_static.php @@ -0,0 +1,31 @@ + + array ( + 'Metowolf\\' => 9, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Metowolf\\' => + array ( + 0 => __DIR__ . '/..' . '/metowolf/meting/src', + ), + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInit7bd602fdce79cdf3c88e3cdb52a761f5::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit7bd602fdce79cdf3c88e3cdb52a761f5::$prefixDirsPsr4; + + }, null, ClassLoader::class); + } +} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json new file mode 100644 index 0000000..006278d --- /dev/null +++ b/vendor/composer/installed.json @@ -0,0 +1,54 @@ +[ + { + "name": "metowolf/meting", + "version": "v1.5.7", + "version_normalized": "1.5.7.0", + "source": { + "type": "git", + "url": "https://github.com/metowolf/Meting.git", + "reference": "54178aa112da5db09f487d862d7ae62cbf7bc060" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/metowolf/Meting/zipball/54178aa112da5db09f487d862d7ae62cbf7bc060", + "reference": "54178aa112da5db09f487d862d7ae62cbf7bc060", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-openssl": "*", + "php": ">=5.4.0" + }, + "suggest": { + "ext-bcmath": "Required to use BC Math calculate RSA.", + "ext-openssl": "Required to use OpenSSL encrypt params." + }, + "time": "2019-06-16T05:55:00+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Metowolf\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "metowolf", + "email": "i@i-meto.com", + "homepage": "https://i-meto.com" + } + ], + "description": "A powerful music API framework to accelerate development.", + "homepage": "https://github.com/metowolf/Meting", + "keywords": [ + "lightweight", + "lighty", + "music api", + "php music" + ] + } +] diff --git a/vendor/metowolf/meting/.editorconfig b/vendor/metowolf/meting/.editorconfig new file mode 100644 index 0000000..341b31d --- /dev/null +++ b/vendor/metowolf/meting/.editorconfig @@ -0,0 +1,24 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.yml] +indent_style = space +indent_size = 2 + +[*.php] +indent_style = space +indent_size = 4 + +[*.sh] +indent_style = space +indent_size = 4 diff --git a/vendor/metowolf/meting/.gitignore b/vendor/metowolf/meting/.gitignore new file mode 100644 index 0000000..ff7f293 --- /dev/null +++ b/vendor/metowolf/meting/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +.idea/ diff --git a/vendor/metowolf/meting/.travis.yml b/vendor/metowolf/meting/.travis.yml new file mode 100644 index 0000000..0fad59c --- /dev/null +++ b/vendor/metowolf/meting/.travis.yml @@ -0,0 +1,28 @@ +language: php + +matrix: + fast_finish: true + + include: + - php: '5.4' + - php: '5.5' + - php: '5.6' + - php: '7.0' + - php: '7.1' + - php: '7.2' + - php: '7.3' + - php: 'nightly' + - php: 'hhvm' + + allow_failures: + - php: '5.4' + - php: '5.5' + - php: '5.6' + - php: '7.0' + - php: 'nightly' + - php: 'hhvm' + +sudo: false + +script: + - find -L . -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l diff --git a/vendor/metowolf/meting/LICENSE b/vendor/metowolf/meting/LICENSE new file mode 100644 index 0000000..81809b5 --- /dev/null +++ b/vendor/metowolf/meting/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 METO + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/metowolf/meting/README.md b/vendor/metowolf/meting/README.md new file mode 100644 index 0000000..355db44 --- /dev/null +++ b/vendor/metowolf/meting/README.md @@ -0,0 +1,92 @@ +

    +Meting +

    + +

    +Author +Version +Downloads +Travis +License +

    + + > :cake: Wow, such a powerful music API framework + +## Introduction +A powerful music API framework to accelerate your development + + **Elegant** - Easy to use, a standardized format for all music platforms. + + **Lightweight** - A single-file library that's less than 46KB. + + **Powerful** - Support various music platforms, including Tencent, NetEase, Xiami, KuGou, Baidu and more. + + **Free** - Under MIT license, need I say more? + +## Requirement +PHP 5.4+ and BCMath, Curl, OpenSSL extension installed. + +## Installation +Require this package, with [Composer](https://getcomposer.org), in the root directory of your project. + +```bash +$ composer require metowolf/meting +``` + +Then you can import the class into your application: + +```php +use Metowolf\Meting; + +$api = new Meting('netease'); + +$data = $api->format(true)->search('Soldier'); +``` + +> **Note:** Meting requires [BCMath](http://php.net/manual/en/book.bc.php), [cURL](http://php.net/manual/en/book.curl.php) and [OpenSSL](http://php.net/manual/en/book.openssl.php) extension in order to work. + + +## Quick Start +```php +require 'vendor/autoload.php'; +// require 'Meting.php'; + +use Metowolf\Meting; + +// Initialize to netease API +$api = new Meting('netease'); + +// Use custom cookie (option) +// $api->cookie('paste your cookie'); + +// Get data +$data = $api->format(true)->search('Soldier', [ + 'page' => 1, + 'limit' => 50 +]); + +echo $data; +// [{"id":35847388,"name":"Hello","artist":["Adele"],"album":"Hello","pic_id":"1407374890649284","url_id":35847388,"lyric_id":35847388,"source":"netease"},{"id":33211676,"name":"Hello","artist":["OMFG"],"album":"Hello",... + +// Parse link +$data = $api->format(true)->url(35847388); + +echo $data; +// {"url":"http:\/\/...","size":4729252,"br":128} +``` + +## More usage + - [docs](https://github.com/metowolf/Meting/wiki) + - [special for netease](https://github.com/metowolf/Meting/wiki/special-for-netease) + +## Join the Discussion + - [Telegram Group](https://t.me/adplayer) + - [Official website](https://i-meto.com) + +## Related Projects + - [Hermit-X (Wordpress)](https://github.com/MoePlayer/Hermit-X) + - [APlayer-Typecho](https://github.com/MoePlayer/APlayer-Typecho) + - [MKOnlineMusicPlayer](https://github.com/mengkunsoft/MKOnlineMusicPlayer) + - [WP-Player](https://github.com/webjyh/WP-Player) + +## Author + +**Meting** © [metowolf](https://github.com/metowolf), Released under the [MIT](./LICENSE) License.
    + +> Blog [@meto](https://i-meto.com) · GitHub [@metowolf](https://github.com/metowolf) · Twitter [@metowolf](https://twitter.com/metowolf) · Telegram Channel [@metooooo](https://t.me/metooooo) diff --git a/vendor/metowolf/meting/composer.json b/vendor/metowolf/meting/composer.json new file mode 100644 index 0000000..0b54c4e --- /dev/null +++ b/vendor/metowolf/meting/composer.json @@ -0,0 +1,38 @@ +{ + "name": "metowolf/meting", + "type": "library", + "description": "A powerful music API framework to accelerate development.", + "keywords": [ + "php music", + "music api", + "lighty", + "lightweight" + ], + "homepage": "https://github.com/metowolf/Meting", + "license": "MIT", + "authors": [ + { + "name": "metowolf", + "email": "i@i-meto.com", + "homepage": "https://i-meto.com" + } + ], + "support": { + "issues": "https://github.com/metowolf/Meting/issues", + "source": "https://github.com/metowolf/Meting" + }, + "require": { + "php": ">=5.4.0", + "ext-curl": "*", + "ext-openssl": "*" + }, + "suggest": { + "ext-bcmath": "Required to use BC Math calculate RSA.", + "ext-openssl": "Required to use OpenSSL encrypt params." + }, + "autoload": { + "psr-4": { + "Metowolf\\" : "src/" + } + } +} diff --git a/vendor/metowolf/meting/src/Meting.php b/vendor/metowolf/meting/src/Meting.php new file mode 100644 index 0000000..198c3ba --- /dev/null +++ b/vendor/metowolf/meting/src/Meting.php @@ -0,0 +1,1365 @@ + + * Released under the MIT license + */ + +namespace Metowolf; + +class Meting +{ + const VERSION = '1.5.7'; + + public $raw; + public $data; + public $info; + public $error; + public $status; + + public $server; + public $proxy = null; + public $format = false; + public $header; + + 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; + } + + public function proxy($value) + { + $this->proxy = $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); + if ($this->proxy) { + curl_setopt($curl, CURLOPT_PROXY, $this->proxy); + } + 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' => 'https://acs.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://mobilecdn.kugou.com/api/v3/search/song', + 'body' => array( + 'api_ver' => 1, + 'area_code' => 1, + 'correct' => 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' => 8990, + ), + 'format' => 'data.info', + ); + break; + case 'baidu': + $api = array( + 'method' => 'GET', + 'url' => 'http://musicapi.taihe.com/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.2.1', + '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->server) { + case 'netease': + $api = array( + 'method' => 'POST', + 'url' => 'http://music.163.com/api/v3/song/detail/', + 'body' => array( + 'c' => '[{"id":'.$id.',"v":0}]', + ), + 'encode' => 'netease_AESCBC', + 'format' => 'songs', + ); + break; + case 'tencent': + $api = array( + 'method' => 'GET', + 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_play_single_song.fcg', + 'body' => array( + 'songmid' => $id, + 'platform' => 'yqq', + 'format' => 'json', + ), + 'format' => 'data', + ); + break; + case 'xiami': + $api = array( + 'method' => 'GET', + 'url' => 'https://acs.m.xiami.com/h5/mtop.alimusic.music.songservice.getsongdetail/1.0/', + 'body' => array( + 'data' => array( + 'songId' => $id, + ), + 'r' => 'mtop.alimusic.music.songservice.getsongdetail', + ), + 'encode' => 'xiami_sign', + 'format' => 'data.data.songDetail', + ); + break; + case 'kugou': + $api = array( + 'method' => 'POST', + 'url' => 'http://m.kugou.com/app/i/getSongInfo.php', + 'body' => array( + 'cmd' => 'playInfo', + 'hash' => $id, + 'from' => 'mkugou', + ), + 'format' => '', + ); + break; + case 'baidu': + $api = array( + 'method' => 'GET', + 'url' => 'http://musicapi.taihe.com/v1/restserver/ting', + 'body' => array( + 'from' => 'qianqianmini', + 'method' => 'baidu.ting.song.getInfos', + 'songid' => $id, + 'res' => 1, + 'platform' => 'darwin', + 'version' => '1.0.0', + ), + 'encode' => 'baidu_AESCBC', + 'format' => 'songinfo', + ); + break; + } + + return $this->exec($api); + } + + public function album($id) + { + switch ($this->server) { + case 'netease': + $api = array( + 'method' => 'POST', + 'url' => 'http://music.163.com/api/v1/album/'.$id, + 'body' => array( + 'total' => 'true', + 'offset' => '0', + 'id' => $id, + 'limit' => '1000', + 'ext' => 'true', + 'private_cloud' => 'true', + ), + 'encode' => 'netease_AESCBC', + 'format' => 'songs', + ); + break; + case 'tencent': + $api = array( + 'method' => 'GET', + 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_album_detail_cp.fcg', + 'body' => array( + 'albummid' => $id, + 'platform' => 'mac', + 'format' => 'json', + 'newsong' => 1, + ), + 'format' => 'data.getSongInfo', + ); + break; + case 'xiami': + $api = array( + 'method' => 'GET', + 'url' => 'https://acs.m.xiami.com/h5/mtop.alimusic.music.albumservice.getalbumdetail/1.0/', + 'body' => array( + 'data' => array( + 'albumId' => $id, + ), + 'r' => 'mtop.alimusic.music.albumservice.getalbumdetail', + ), + 'encode' => 'xiami_sign', + 'format' => 'data.data.albumDetail.songs', + ); + break; + case 'kugou': + $api = array( + 'method' => 'GET', + 'url' => 'http://mobilecdn.kugou.com/api/v3/album/song', + 'body' => array( + 'albumid' => $id, + 'area_code' => 1, + 'plat' => 2, + 'page' => 1, + 'pagesize' => -1, + 'version' => 8990, + ), + 'format' => 'data.info', + ); + break; + case 'baidu': + $api = array( + 'method' => 'GET', + 'url' => 'http://musicapi.taihe.com/v1/restserver/ting', + 'body' => array( + 'from' => 'qianqianmini', + 'method' => 'baidu.ting.album.getAlbumInfo', + 'album_id' => $id, + 'platform' => 'darwin', + 'version' => '11.2.1', + ), + 'format' => 'songlist', + ); + break; + } + + return $this->exec($api); + } + + public function artist($id, $limit = 50) + { + switch ($this->server) { + case 'netease': + $api = array( + 'method' => 'POST', + 'url' => 'http://music.163.com/api/v1/artist/'.$id, + 'body' => array( + 'ext' => 'true', + 'private_cloud' => 'true', + 'ext' => 'true', + 'top' => $limit, + 'id' => $id, + ), + 'encode' => 'netease_AESCBC', + 'format' => 'hotSongs', + ); + break; + case 'tencent': + $api = array( + 'method' => 'GET', + 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_singer_track_cp.fcg', + 'body' => array( + 'singermid' => $id, + 'begin' => 0, + 'num' => $limit, + 'order' => 'listen', + 'platform' => 'mac', + 'newsong' => 1, + ), + 'format' => 'data.list', + ); + break; + case 'xiami': + $api = array( + 'method' => 'GET', + 'url' => 'https://acs.m.xiami.com/h5/mtop.alimusic.music.songservice.getartistsongs/1.0/', + 'body' => array( + 'data' => array( + 'artistId' => $id, + 'pagingVO' => array( + 'page' => 1, + 'pageSize' => $limit, + ), + ), + 'r' => 'mtop.alimusic.music.songservice.getartistsongs', + ), + 'encode' => 'xiami_sign', + 'format' => 'data.data.songs', + ); + break; + case 'kugou': + $api = array( + 'method' => 'GET', + 'url' => 'http://mobilecdn.kugou.com/api/v3/singer/song', + 'body' => array( + 'singerid' => $id, + 'area_code' => 1, + 'page' => 1, + 'plat' => 0, + 'pagesize' => $limit, + 'version' => 8990, + ), + 'format' => 'data.info', + ); + break; + case 'baidu': + $api = array( + 'method' => 'GET', + 'url' => 'http://musicapi.taihe.com/v1/restserver/ting', + 'body' => array( + 'from' => 'qianqianmini', + 'method' => 'baidu.ting.artist.getSongList', + 'artistid' => $id, + 'limits' => $limit, + 'platform' => 'darwin', + 'offset' => 0, + 'tinguid' => 0, + 'version' => '11.2.1', + ), + 'format' => 'songlist', + ); + break; + } + + return $this->exec($api); + } + + public function playlist($id) + { + switch ($this->server) { + case 'netease': + $api = array( + 'method' => 'POST', + 'url' => 'http://music.163.com/api/v3/playlist/detail', + 'body' => array( + 's' => '0', + 'id' => $id, + 'n' => '1000', + 't' => '0', + ), + 'encode' => 'netease_AESCBC', + 'format' => 'playlist.tracks', + ); + break; + case 'tencent': + $api = array( + 'method' => 'GET', + 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_v8_playlist_cp.fcg', + 'body' => array( + 'id' => $id, + 'format' => 'json', + 'newsong' => 1, + 'platform' => 'jqspaframe.json', + ), + 'format' => 'data.cdlist.0.songlist', + ); + break; + case 'xiami': + $api = array( + 'method' => 'GET', + 'url' => 'https://acs.m.xiami.com/h5/mtop.alimusic.music.list.collectservice.getcollectdetail/1.0/', + 'body' => array( + 'data' => array( + 'listId' => $id, + 'isFullTags' => false, + 'pagingVO' => array( + 'page' => 1, + 'pageSize' => 1000, + ), + ), + 'r' => 'mtop.alimusic.music.list.collectservice.getcollectdetail', + ), + 'encode' => 'xiami_sign', + 'format' => 'data.data.collectDetail.songs', + ); + break; + case 'kugou': + $api = array( + 'method' => 'GET', + 'url' => 'http://mobilecdn.kugou.com/api/v3/special/song', + 'body' => array( + 'specialid' => $id, + 'area_code' => 1, + 'page' => 1, + 'plat' => 2, + 'pagesize' => -1, + 'version' => 8990, + ), + 'format' => 'data.info', + ); + break; + case 'baidu': + $api = array( + 'method' => 'GET', + 'url' => 'http://musicapi.taihe.com/v1/restserver/ting', + 'body' => array( + 'from' => 'qianqianmini', + 'method' => 'baidu.ting.diy.gedanInfo', + 'listid' => $id, + 'platform' => 'darwin', + 'version' => '11.2.1', + ), + 'format' => 'content', + ); + break; + } + + return $this->exec($api); + } + + public function url($id, $br = 320) + { + switch ($this->server) { + case 'netease': + $api = array( + 'method' => 'POST', + 'url' => 'http://music.163.com/api/song/enhance/player/url', + 'body' => array( + 'ids' => array($id), + 'br' => $br * 1000, + ), + 'encode' => 'netease_AESCBC', + 'decode' => 'netease_url', + ); + break; + case 'tencent': + $api = array( + 'method' => 'GET', + 'url' => 'https://c.y.qq.com/v8/fcg-bin/fcg_play_single_song.fcg', + 'body' => array( + 'songmid' => $id, + 'platform' => 'yqq', + 'format' => 'json', + ), + 'decode' => 'tencent_url', + ); + break; + case 'xiami': + $api = array( + 'method' => 'GET', + 'url' => 'https://acs.m.xiami.com/h5/mtop.alimusic.music.songservice.getsongs/1.0/', + 'body' => array( + 'data' => array( + 'songIds' => array( + $id, + ), + ), + 'r' => 'mtop.alimusic.music.songservice.getsongs', + ), + 'encode' => 'xiami_sign', + 'decode' => 'xiami_url', + ); + break; + case 'kugou': + $api = array( + 'method' => 'POST', + 'url' => 'http://media.store.kugou.com/v1/get_res_privilege', + 'body' => json_encode( + array( + 'relate' => 1, + 'userid' => '0', + 'vip' => 0, + 'appid' => 1000, + 'token' => '', + 'behavior' => 'download', + 'area_code' => '1', + 'clientver' => '8990', + 'resource' => array(array( + 'id' => 0, + 'type' => 'audio', + 'hash' => $id, + )), ) + ), + 'decode' => 'kugou_url', + ); + break; + case 'baidu': + $api = array( + 'method' => 'GET', + 'url' => 'http://musicapi.taihe.com/v1/restserver/ting', + 'body' => array( + 'from' => 'qianqianmini', + 'method' => 'baidu.ting.song.getInfos', + 'songid' => $id, + 'res' => 1, + 'platform' => 'darwin', + 'version' => '1.0.0', + ), + 'encode' => 'baidu_AESCBC', + 'decode' => 'baidu_url', + ); + break; + } + $this->temp['br'] = $br; + + return $this->exec($api); + } + + public function lyric($id) + { + switch ($this->server) { + case 'netease': + $api = array( + 'method' => 'POST', + 'url' => 'http://music.163.com/api/song/lyric', + 'body' => array( + 'id' => $id, + 'os' => 'linux', + 'lv' => -1, + 'kv' => -1, + 'tv' => -1, + ), + 'encode' => 'netease_AESCBC', + 'decode' => 'netease_lyric', + ); + break; + case 'tencent': + $api = array( + 'method' => 'GET', + 'url' => 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg', + 'body' => array( + 'songmid' => $id, + 'g_tk' => '5381', + ), + 'decode' => 'tencent_lyric', + ); + break; + case 'xiami': + $api = array( + 'method' => 'GET', + 'url' => 'https://acs.m.xiami.com/h5/mtop.alimusic.music.lyricservice.getsonglyrics/1.0/', + 'body' => array( + 'data' => array( + 'songId' => $id, + ), + 'r' => 'mtop.alimusic.music.lyricservice.getsonglyrics', + ), + 'encode' => 'xiami_sign', + 'decode' => 'xiami_lyric', + ); + break; + case 'kugou': + $api = array( + 'method' => 'GET', + 'url' => 'http://krcs.kugou.com/search', + 'body' => array( + 'keyword' => '%20-%20', + 'ver' => 1, + 'hash' => $id, + 'client' => 'mobi', + 'man' => 'yes', + ), + 'decode' => 'kugou_lyric', + ); + break; + case 'baidu': + $api = array( + 'method' => 'GET', + 'url' => 'http://musicapi.taihe.com/v1/restserver/ting', + 'body' => array( + 'from' => 'qianqianmini', + 'method' => 'baidu.ting.song.lry', + 'songid' => $id, + 'platform' => 'darwin', + 'version' => '1.0.0', + ), + 'decode' => 'baidu_lyric', + ); + break; + } + + return $this->exec($api); + } + + public function pic($id, $size = 300) + { + switch ($this->server) { + case 'netease': + $url = 'https://p3.music.126.net/'.$this->netease_encryptId($id).'/'.$id.'.jpg?param='.$size.'y'.$size; + break; + case 'tencent': + $url = 'https://y.gtimg.cn/music/photo_new/T002R'.$size.'x'.$size.'M000'.$id.'.jpg?max_age=2592000'; + break; + case 'xiami': + $format = $this->format; + $data = $this->format(false)->song($id); + $this->format = $format; + $data = json_decode($data, true); + $url = $data['data']['data']['songDetail']['albumLogo']; + $url = str_replace('http:', 'https:', $url).'@1e_1c_100Q_'.$size.'h_'.$size.'w'; + break; + case 'kugou': + $format = $this->format; + $data = $this->format(false)->song($id); + $this->format = $format; + $data = json_decode($data, true); + $url = $data['imgUrl']; + $url = str_replace('{size}', '400', $url); + break; + case 'baidu': + $format = $this->format; + $data = $this->format(false)->song($id); + $this->format = $format; + $data = json_decode($data, true); + $url = isset($data['songinfo']['pic_radio']) ? $data['songinfo']['pic_radio'] : $data['songinfo']['pic_small']; + break; + } + + return json_encode(array('url' => $url)); + } + + private function curlset() + { + switch ($this->server) { + case 'netease': + return array( + 'Referer' => 'https://music.163.com/', + 'Cookie' => 'appver=1.5.9; os=osx; __remember_me=true; osver=%E7%89%88%E6%9C%AC%2010.13.5%EF%BC%88%E7%89%88%E5%8F%B7%2017F77%EF%BC%89;', + 'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/605.1.15 (KHTML, like Gecko)', + 'X-Real-IP' => long2ip(mt_rand(1884815360, 1884890111)), + 'Accept' => '*/*', + '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', + ); + case 'tencent': + return array( + 'Referer' => 'http://y.qq.com', + 'Cookie' => 'pgv_pvi=22038528; pgv_si=s3156287488; pgv_pvid=5535248600; yplayer_open=1; ts_last=y.qq.com/portal/player.html; ts_uid=4847550686; yq_index=0; qqmusic_fromtag=66; player_exist=1', + 'User-Agent' => 'QQ%E9%9F%B3%E4%B9%90/54409 CFNetwork/901.1 Darwin/17.6.0 (x86_64)', + 'Accept' => '*/*', + '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', + ); + case 'xiami': + return array( + 'Cookie' => '_m_h5_tk=15d3402511a022796d88b249f83fb968_1511163656929; _m_h5_tk_enc=b6b3e64d81dae577fc314b5c5692df3c', + 'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) XIAMI-MUSIC/3.1.1 Chrome/56.0.2924.87 Electron/1.6.11 Safari/537.36', + 'Accept' => 'application/json', + 'Content-type' => 'application/x-www-form-urlencoded', + 'Accept-Language' => 'zh-CN', + ); + case 'kugou': + return array( + 'User-Agent' => 'IPhone-8990-searchSong', + 'UNI-UserAgent' => 'iOS11.4-Phone8990-1009-0-WiFi', + ); + case 'baidu': + return array( + 'Cookie' => 'BAIDUID='.$this->getRandomHex(32).':FG=1', + 'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) baidu-music/1.2.1 Chrome/66.0.3359.181 Electron/3.0.5 Safari/537.36', + 'Accept' => '*/*', + 'Content-type' => 'application/json;charset=UTF-8', + 'Accept-Language' => 'zh-CN', + ); + } + } + + private function getRandomHex($length) + { + if (function_exists('random_bytes')) { + return bin2hex(random_bytes($length / 2)); + } + if (function_exists('mcrypt_create_iv')) { + return bin2hex(mcrypt_create_iv($length / 2, MCRYPT_DEV_URANDOM)); + } + if (function_exists('openssl_random_pseudo_bytes')) { + return bin2hex(openssl_random_pseudo_bytes($length / 2)); + } + } + + private function bchexdec($hex) + { + $dec = 0; + $len = strlen($hex); + for ($i = 1; $i <= $len; $i++) { + $dec = bcadd($dec, bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i)))); + } + + return $dec; + } + + private function bcdechex($dec) + { + $hex = ''; + do { + $last = bcmod($dec, 16); + $hex = dechex($last).$hex; + $dec = bcdiv(bcsub($dec, $last), 16); + } while ($dec > 0); + + return $hex; + } + + private function str2hex($string) + { + $hex = ''; + for ($i = 0; $i < strlen($string); $i++) { + $ord = ord($string[$i]); + $hexCode = dechex($ord); + $hex .= substr('0'.$hexCode, -2); + } + + return $hex; + } + + private function netease_AESCBC($api) + { + $modulus = '157794750267131502212476817800345498121872783333389747424011531025366277535262539913701806290766479189477533597854989606803194253978660329941980786072432806427833685472618792592200595694346872951301770580765135349259590167490536138082469680638514416594216629258349130257685001248172188325316586707301643237607'; + $pubkey = '65537'; + $nonce = '0CoJUm6Qyw8W8jud'; + $vi = '0102030405060708'; + + if (extension_loaded('bcmath')) { + $skey = $this->getRandomHex(16); + } else { + $skey = 'B3v3kH4vRPWRJFfH'; + } + + $body = json_encode($api['body']); + + if (function_exists('openssl_encrypt')) { + $body = openssl_encrypt($body, 'aes-128-cbc', $nonce, false, $vi); + $body = openssl_encrypt($body, 'aes-128-cbc', $skey, false, $vi); + } else { + $pad = 16 - (strlen($body) % 16); + $body = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $nonce, $body.str_repeat(chr($pad), $pad), MCRYPT_MODE_CBC, $vi)); + $pad = 16 - (strlen($body) % 16); + $body = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $skey, $body.str_repeat(chr($pad), $pad), MCRYPT_MODE_CBC, $vi)); + } + + if (extension_loaded('bcmath')) { + $skey = strrev(utf8_encode($skey)); + $skey = $this->bchexdec($this->str2hex($skey)); + $skey = bcpowmod($skey, $pubkey, $modulus); + $skey = $this->bcdechex($skey); + $skey = str_pad($skey, 256, '0', STR_PAD_LEFT); + } else { + $skey = '85302b818aea19b68db899c25dac229412d9bba9b3fcfe4f714dc016bc1686fc446a08844b1f8327fd9cb623cc189be00c5a365ac835e93d4858ee66f43fdc59e32aaed3ef24f0675d70172ef688d376a4807228c55583fe5bac647d10ecef15220feef61477c28cae8406f6f9896ed329d6db9f88757e31848a6c2ce2f94308'; + } + + $api['url'] = str_replace('/api/', '/weapi/', $api['url']); + $api['body'] = array( + 'params' => $body, + 'encSecKey' => $skey, + ); + + return $api; + } + + private function baidu_AESCBC($api) + { + $key = 'DBEECF8C50FD160E'; + $vi = '1231021386755796'; + + $data = 'songid='.$api['body']['songid'].'&ts='.intval(microtime(true) * 1000); + + if (function_exists('openssl_encrypt')) { + $data = openssl_encrypt($data, 'aes-128-cbc', $key, false, $vi); + } else { + $pad = 16 - (strlen($data) % 16); + $data = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data.str_repeat(chr($pad), $pad), MCRYPT_MODE_CBC, $vi)); + } + + $api['body']['e'] = $data; + + return $api; + } + + private function xiami_sign($api) + { + $data = $this->curl('https://acs.m.xiami.com/h5/mtop.alimusic.recommend.songservice.getdailysongs/1.0/?appKey=12574478&t=1560663823000&dataType=json&data=%7B%22requestStr%22%3A%22%7B%5C%22header%5C%22%3A%7B%5C%22platformId%5C%22%3A%5C%22mac%5C%22%7D%2C%5C%22model%5C%22%3A%5B%5D%7D%22%7D&api=mtop.alimusic.recommend.songservice.getdailysongs&v=1.0&type=originaljson&sign=22ad1377ee193f3e2772c17c6192b17c', null, 1); + preg_match_all('/_m_h5[^;]+/', $data->raw, $match); + $this->header['Cookie'] = $match[0][0].'; '.$match[0][1]; + $data = json_encode(array( + 'requestStr' => json_encode(array( + 'header' => array( + 'platformId' => 'mac', + ), + 'model' => $api['body']['data'], + )), + )); + $appkey = '12574478'; + $cookie = $this->header['Cookie']; + preg_match('/_m_h5_tk=([^_]+)/', $cookie, $match); + $token = $match[1]; + $t = time() * 1000; + $sign = md5(sprintf('%s&%s&%s&%s', $token, $t, $appkey, $data)); + $api['body'] = array( + 'appKey' => $appkey, + 't' => $t, + 'dataType' => 'json', + 'data' => $data, + 'api' => $api['body']['r'], + 'v' => '1.0', + 'type' => 'originaljson', + 'sign' => $sign, + ); + + return $api; + } + + private function netease_encryptId($id) + { + $magic = str_split('3go8&$8*3*3h0k(2)2'); + $song_id = str_split($id); + for ($i = 0; $i < count($song_id); $i++) { + $song_id[$i] = chr(ord($song_id[$i]) ^ ord($magic[$i % count($magic)])); + } + $result = base64_encode(md5(implode('', $song_id), 1)); + $result = str_replace(array('/', '+'), array('_', '-'), $result); + + return $result; + } + + private function netease_url($result) + { + $data = json_decode($result, true); + if (isset($data['data'][0]['uf']['url'])) { + $data['data'][0]['url'] = $data['data'][0]['uf']['url']; + } + if (isset($data['data'][0]['url'])) { + $url = array( + 'url' => $data['data'][0]['url'], + 'size' => $data['data'][0]['size'], + 'br' => $data['data'][0]['br'] / 1000, + ); + } else { + $url = array( + 'url' => '', + 'size' => 0, + 'br' => -1, + ); + } + + return json_encode($url); + } + + private function tencent_url($result) + { + $data = json_decode($result, true); + $guid = mt_rand() % 10000000000; + + $type = array( + array('size_320mp3', 320, 'M800', 'mp3'), + array('size_192aac', 192, 'C600', 'm4a'), + array('size_128mp3', 128, 'M500', 'mp3'), + array('size_96aac', 96, 'C400', 'm4a'), + array('size_48aac', 48, 'C200', 'm4a'), + array('size_24aac', 24, 'C100', 'm4a'), + ); + + $payload = array( + 'req_0' => array( + 'module' => 'vkey.GetVkeyServer', + 'method' => 'CgiGetVkey', + 'param' => array( + 'guid' => (string) $guid, + 'songmid' => array(), + 'filename' => array(), + 'songtype' => array(), + 'uin' => '0', + 'loginflag' => 1, + 'platform' => '20', + ), + ), + ); + + foreach ($type as $vo) { + $payload['req_0']['param']['songmid'][] = $data['data'][0]['mid']; + $payload['req_0']['param']['filename'][] = $vo[2].$data['data'][0]['file']['media_mid'].'.'.$vo[3]; + $payload['req_0']['param']['songtype'][] = $data['data'][0]['type']; + } + + $api = array( + 'method' => 'GET', + 'url' => 'https://u.y.qq.com/cgi-bin/musicu.fcg', + 'body' => array( + 'format' => 'json', + 'platform' => 'yqq.json', + 'needNewCode' => 0, + 'data' => json_encode($payload), + ), + ); + $response = json_decode($this->exec($api), true); + $vkeys = $response['req_0']['data']['midurlinfo']; + + foreach ($type as $index => $vo) { + if ($data['data'][0]['file'][$vo[0]] && $vo[1] <= $this->temp['br']) { + if (!empty($vkeys[$index]['vkey'])) { + $url = array( + 'url' => $response['req_0']['data']['sip'][0].$vkeys[$index]['purl'], + 'size' => $data['data'][0]['file'][$vo[0]], + 'br' => $vo[1], + ); + break; + } + } + } + if (!isset($url['url'])) { + $url = array( + 'url' => '', + 'size' => 0, + 'br' => -1, + ); + } + + return json_encode($url); + } + + private function xiami_url($result) + { + $data = json_decode($result, true); + + $type = array( + 's' => 740, + 'h' => 320, + 'l' => 128, + 'f' => 64, + 'e' => 32, + ); + $max = 0; + $url = array(); + foreach ($data['data']['data']['songs'][0]['listenFiles'] as $vo) { + if ($type[$vo['quality']] <= $this->temp['br'] && $type[$vo['quality']] > $max) { + $max = $type[$vo['quality']]; + $url = array( + 'url' => $vo['listenFile'], + 'size' => $vo['fileSize'], + 'br' => $type[$vo['quality']], + ); + } + } + if (!isset($url['url'])) { + $url = array( + 'url' => '', + 'size' => 0, + 'br' => -1, + ); + } + + return json_encode($url); + } + + private function kugou_url($result) + { + $data = json_decode($result, true); + + $max = 0; + $url = array(); + foreach ($data['data'][0]['relate_goods'] as $vo) { + if ($vo['info']['bitrate'] <= $this->temp['br'] && $vo['info']['bitrate'] > $max) { + $api = array( + 'method' => 'GET', + 'url' => 'http://trackercdn.kugou.com/i/v2/', + 'body' => array( + 'hash' => $vo['hash'], + 'key' => md5($vo['hash'].'kgcloudv2'), + 'pid' => 3, + 'behavior' => 'play', + 'cmd' => '25', + 'version' => 8990, + ), + ); + $t = json_decode($this->exec($api), true); + if (isset($t['url'])) { + $max = $t['bitRate'] / 1000; + $url = array( + 'url' => reset($t['url']), + 'size' => $t['fileSize'], + 'br' => $t['bitRate'] / 1000, + ); + } + } + } + if (!isset($url['url'])) { + $url = array( + 'url' => '', + 'size' => 0, + 'br' => -1, + ); + } + + return json_encode($url); + } + + private function baidu_url($result) + { + $data = json_decode($result, true); + + $max = 0; + $url = array(); + foreach ($data['songurl']['url'] as $vo) { + if ($vo['file_bitrate'] <= $this->temp['br'] && $vo['file_bitrate'] > $max) { + $url = array( + 'url' => $vo['file_link'], + 'br' => $vo['file_bitrate'], + ); + } + } + if (!isset($url['url'])) { + $url = array( + 'url' => '', + 'br' => -1, + ); + } + + return json_encode($url); + } + + private function netease_lyric($result) + { + $result = json_decode($result, true); + $data = array( + 'lyric' => isset($result['lrc']['lyric']) ? $result['lrc']['lyric'] : '', + 'tlyric' => isset($result['tlyric']['lyric']) ? $result['tlyric']['lyric'] : '', + ); + + return json_encode($data); + } + + private function tencent_lyric($result) + { + $result = substr($result, 18, -1); + $result = json_decode($result, true); + $data = array( + '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) + { + $result = json_decode($result, true); + + if (count($result['data']['data']['lyrics'])) { + $data = $result['data']['data']['lyrics'][0]['content']; + $data = preg_replace('/<[^>]+>/', '', $data); + preg_match_all('/\[([\d:\.]+)\](.*)\s\[x-trans\](.*)/i', $data, $match); + if (count($match[0])) { + for ($i = 0; $i < count($match[0]); $i++) { + $A[] = '['.$match[1][$i].']'.$match[2][$i]; + $B[] = '['.$match[1][$i].']'.$match[3][$i]; + } + $arr = array( + 'lyric' => str_replace($match[0], $A, $data), + 'tlyric' => str_replace($match[0], $B, $data), + ); + } else { + $arr = array( + 'lyric' => $data, + 'tlyric' => '', + ); + } + } else { + $arr = array( + 'lyric' => '', + 'tlyric' => '', + ); + } + + return json_encode($arr); + } + + private function kugou_lyric($result) + { + $result = json_decode($result, true); + $api = array( + 'method' => 'GET', + 'url' => 'http://lyrics.kugou.com/download', + 'body' => array( + 'charset' => 'utf8', + 'accesskey' => $result['candidates'][0]['accesskey'], + 'id' => $result['candidates'][0]['id'], + 'client' => 'mobi', + 'fmt' => 'lrc', + 'ver' => 1, + ), + ); + $data = json_decode($this->exec($api), true); + $arr = array( + 'lyric' => base64_decode($data['content']), + 'tlyric' => '', + ); + + return json_encode($arr); + } + + private function baidu_lyric($result) + { + $result = json_decode($result, true); + $data = array( + 'lyric' => isset($result['lrcContent']) ? $result['lrcContent'] : '', + 'tlyric' => '', + ); + + return json_encode($data); + } + + private function format_netease($data) + { + $result = array( + 'id' => $data['id'], + 'name' => $data['name'], + 'artist' => array(), + 'album' => $data['al']['name'], + 'pic_id' => isset($data['al']['pic_str']) ? $data['al']['pic_str'] : $data['al']['pic'], + 'url_id' => $data['id'], + 'lyric_id' => $data['id'], + 'source' => 'netease', + ); + if (isset($data['al']['picUrl'])) { + preg_match('/\/(\d+)\./', $data['al']['picUrl'], $match); + $result['pic_id'] = $match[1]; + } + foreach ($data['ar'] as $vo) { + $result['artist'][] = $vo['name']; + } + + return $result; + } + + private function format_tencent($data) + { + if (isset($data['musicData'])) { + $data = $data['musicData']; + } + $result = array( + 'id' => $data['mid'], + 'name' => $data['name'], + 'artist' => array(), + 'album' => trim($data['album']['title']), + 'pic_id' => $data['album']['mid'], + 'url_id' => $data['mid'], + 'lyric_id' => $data['mid'], + 'source' => 'tencent', + ); + foreach ($data['singer'] as $vo) { + $result['artist'][] = $vo['name']; + } + + return $result; + } + + private function format_xiami($data) + { + $result = array( + 'id' => $data['songId'], + 'name' => $data['songName'], + 'artist' => array(), + 'album' => $data['albumName'], + 'pic_id' => $data['songId'], + 'url_id' => $data['songId'], + 'lyric_id' => $data['songId'], + 'source' => 'xiami', + ); + foreach ($data['singerVOs'] as $vo) { + $result['artist'][] = $vo['artistName']; + } + + return $result; + } + + private function format_kugou($data) + { + $result = array( + 'id' => $data['hash'], + 'name' => isset($data['filename']) ? $data['filename'] : $data['fileName'], + 'artist' => array(), + 'album' => isset($data['album_name']) ? $data['album_name'] : '', + 'url_id' => $data['hash'], + 'pic_id' => $data['hash'], + 'lyric_id' => $data['hash'], + 'source' => 'kugou', + ); + list($result['artist'], $result['name']) = explode(' - ', $result['name'], 2); + $result['artist'] = explode('、', $result['artist']); + + return $result; + } + + private function format_baidu($data) + { + $result = array( + 'id' => $data['song_id'], + 'name' => $data['title'], + 'artist' => explode(',', $data['author']), + 'album' => $data['album_title'], + 'pic_id' => $data['song_id'], + 'url_id' => $data['song_id'], + 'lyric_id' => $data['song_id'], + 'source' => 'baidu', + ); + + return $result; + } +}