diff --git a/package/ctcgfw/luci-app-unblockneteasemusic/Makefile b/package/ctcgfw/luci-app-unblockneteasemusic/Makefile index ec31e5184d..bea1e329f7 100644 --- a/package/ctcgfw/luci-app-unblockneteasemusic/Makefile +++ b/package/ctcgfw/luci-app-unblockneteasemusic/Makefile @@ -8,11 +8,11 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI support for UnblockNeteaseMusic -LUCI_DEPENDS:=+bash +busybox +coreutils-nohup +curl +dnsmasq-full +ipset +libopenssl +node +LUCI_DEPENDS:=+bash +busybox +coreutils +coreutils-nohup +curl +dnsmasq-full +ipset +libopenssl +node LUCI_PKGARCH:=all PKG_NAME:=luci-app-unblockneteasemusic PKG_VERSION:=2.8 -PKG_RELEASE:=5 +PKG_RELEASE:=7 PKG_MAINTAINER:=[CTCGFW]Project-OpenWrt diff --git a/package/ctcgfw/luci-app-unblockneteasemusic/luasrc/model/cbi/unblockneteasemusic.lua b/package/ctcgfw/luci-app-unblockneteasemusic/luasrc/model/cbi/unblockneteasemusic.lua index c85b21b27a..8856eabefc 100644 --- a/package/ctcgfw/luci-app-unblockneteasemusic/luasrc/model/cbi/unblockneteasemusic.lua +++ b/package/ctcgfw/luci-app-unblockneteasemusic/luasrc/model/cbi/unblockneteasemusic.lua @@ -27,21 +27,10 @@ music_source.description = translate("自定义模式下,多个音源请用空 music_source.default = "default" music_source.rmempty = false -neteasemusic_cookie = s:option(Value, "neteasemusic_cookie", translate("NeteaseMusic Cookie")) -neteasemusic_cookie.description = translate("在 music.163.com 获取,需要MUSIC_U值") -neteasemusic_cookie.datatype = "string" -neteasemusic_cookie:depends("music_source", "netease") - -qq_cookie = s:option(Value, "qq_cookie", translate("QQ Cookie")) -qq_cookie.description = translate("在 y.qq.com 获取,需要uin和qm_keyst值") -qq_cookie.placeholder = "uin=; qm_keyst=" -qq_cookie.datatype = "string" -qq_cookie:depends("music_source", "qq") - -youtube_key = s:option(Value, "youtube_key", translate("Youtube API Key")) -youtube_key.description = translate("API Key申请地址:https://developers.google.com/youtube/v3/getting-started#before-you-start") -youtube_key.datatype = "string" -youtube_key:depends("music_source", "youtube") +enable_flac = s:option(Flag, "enable_flac", translate("启用无损音质")) +enable_flac.description = translate("目前仅支持QQ、酷我、咪咕音源") +enable_flac.default = 0 +enable_flac.rmempty = false replace_music_source = s:option(ListValue, "replace_music_source", translate("强制音乐音源替换")) replace_music_source:value("dont_replace", translate("不强制替换音乐音源")) @@ -53,10 +42,10 @@ replace_music_source.description = translate("当音乐音质低于指定数值 replace_music_source.default = "dont_replace" replace_music_source.rmempty = false -enable_flac = s:option(Flag, "enable_flac", translate("启用无损音质")) -enable_flac.description = translate("目前仅支持QQ、酷我、咪咕音源") -enable_flac.default = 0 -enable_flac.rmempty = false +use_remote_qq_server = s:option(Flag, "use_remote_qq_server", translate("使用云端QQ音源解析")) +use_remote_qq_server.description = translate("通过云端服务器以获取QQ音源信息,无需开通QQ绿钻") +use_remote_qq_server.default = 0 +use_remote_qq_server.rmempty = false auto_update = s:option(Flag, "auto_update", translate("启用自动更新")) auto_update.description = translate("启用后,每天将定时自动检查最新版本并更新") @@ -135,6 +124,27 @@ hijack.description = translate("如果使用Hosts劫持,程序监听的HTTP/HT hijack.default = "dont_hijack" hijack:depends("advanced_mode", 1) +use_custom_cookie = s:option(Flag, "use_custom_cookie", translate("使用自定义 Cookie")) +use_custom_cookie.description = translate("使用自定义 Cookie 请求音源接口") +use_custom_cookie.default = 0 +use_custom_cookie:depends("advanced_mode", 1) + +neteasemusic_cookie = s:option(Value, "neteasemusic_cookie", translate("NeteaseMusic Cookie")) +neteasemusic_cookie.description = translate("在 music.163.com 获取,需要MUSIC_U值") +neteasemusic_cookie.datatype = "string" +neteasemusic_cookie:depends("use_custom_cookie", 1) + +qq_cookie = s:option(Value, "qq_cookie", translate("QQ Cookie")) +qq_cookie.description = translate("在 y.qq.com 获取,需要uin和qm_keyst值") +qq_cookie.placeholder = "uin=; qm_keyst=" +qq_cookie.datatype = "string" +qq_cookie:depends("use_custom_cookie", 1) + +youtube_key = s:option(Value, "youtube_key", translate("Youtube API Key")) +youtube_key.description = translate("API Key申请地址:https://developers.google.com/youtube/v3/getting-started#before-you-start") +youtube_key.datatype = "string" +youtube_key:depends("use_custom_cookie", 1) + keep_core_when_upgrade = s:option(Flag, "keep_core_when_upgrade", translate("升级时保留核心程序")) keep_core_when_upgrade.description = translate("默认情况下,在OpenWrt升级后会导致核心程序丢失,开启此选项后会保留当前下载的核心程序") keep_core_when_upgrade.default = 0 diff --git a/package/ctcgfw/luci-app-unblockneteasemusic/root/etc/config/unblockneteasemusic b/package/ctcgfw/luci-app-unblockneteasemusic/root/etc/config/unblockneteasemusic index ba17dbff36..6f3f5bb65a 100644 --- a/package/ctcgfw/luci-app-unblockneteasemusic/root/etc/config/unblockneteasemusic +++ b/package/ctcgfw/luci-app-unblockneteasemusic/root/etc/config/unblockneteasemusic @@ -2,24 +2,10 @@ config unblockneteasemusic option enable '0' option music_source 'default' - option neteasemusic_cookie '' - option qq_cookie '' - option youtube_key '' - option replace_music_source 'dont_replace' option enable_flac '0' + option replace_music_source 'dont_replace' + option use_remote_qq_server '0' option auto_update '1' option update_time '3' option daemon_enable '1' option advanced_mode '0' - option http_port '5200' - option https_port '5201' - option endpoint_url 'http://music.163.com' - option hijack_ways 'use_ipset' - option keep_core_when_upgrade '0' - option pub_access '0' - option strict_mode '0' - option netease_server_ip '59.111.181.38' - option proxy_server_ip '' - option self_issue_cert_crt '/usr/share/unblockneteasemusic/core/server.crt' - option self_issue_cert_key '/usr/share/unblockneteasemusic/core/server.key' - diff --git a/package/ctcgfw/luci-app-unblockneteasemusic/root/etc/init.d/unblockneteasemusic b/package/ctcgfw/luci-app-unblockneteasemusic/root/etc/init.d/unblockneteasemusic index 8b4f92e561..71ec7a393e 100755 --- a/package/ctcgfw/luci-app-unblockneteasemusic/root/etc/init.d/unblockneteasemusic +++ b/package/ctcgfw/luci-app-unblockneteasemusic/root/etc/init.d/unblockneteasemusic @@ -6,6 +6,7 @@ START=92 STOP=10 NAME="unblockneteasemusic" +UPGRADE_CONF="/lib/upgrade/keep.d/$NAME" uci_get_by_type() { local "ret" @@ -28,16 +29,12 @@ lan_addr="$(uci get network.lan.ipaddr)" enable="$(uci_get_by_type "$NAME" "enable" "0")" music_source="$(uci_get_by_type "$NAME" "music_source" "default")" -neteasemusic_cookie="$(uci_get_by_type "$NAME" "neteasemusic_cookie")" -qq_cookie="$(uci_get_by_type "$NAME" "qq_cookie")" -youtube_key="$(uci_get_by_type "$NAME" "youtube_key")" -replace_music_source="$(uci_get_by_type "$NAME" "replace_music_source" "dont_replace")" enable_flac="$(uci_get_by_type "$NAME" "enable_flac" "0")" -[ "${enable_flac}" -eq "1" ] && un_env="ENABLE_FLAC=true" +[ "${enable_flac}" -eq "1" ] && export ENABLE_FLAC="true" +replace_music_source="$(uci_get_by_type "$NAME" "replace_music_source" "dont_replace")" -endpoint_url="$(uci_get_by_type "$NAME" "endpoint_url" "http://music.163.com")" -hijack_ways="$(uci_get_by_type "$NAME" "hijack_ways" "use_ipset")" +use_remote_qq_server="$(uci_get_by_type "$NAME" "use_remote_qq_server")" auto_update="$(uci_get_by_type "$NAME" "auto_update" "1")" update_time="$(uci_get_by_type "$NAME" "update_time" "3")" @@ -45,6 +42,15 @@ update_time="$(uci_get_by_type "$NAME" "update_time" "3")" http_port="$(uci_get_by_type "$NAME" "http_port" "5200")" https_port="$(uci_get_by_type "$NAME" "https_port" "5201")" +endpoint_url="$(uci_get_by_type "$NAME" "endpoint_url" "http://music.163.com")" +hijack_ways="$(uci_get_by_type "$NAME" "hijack_ways" "use_ipset")" + +neteasemusic_cookie="$(uci_get_by_type "$NAME" "neteasemusic_cookie")" +qq_cookie="$(uci_get_by_type "$NAME" "qq_cookie")" +[ -n "${qq_cookie}" ] && export QQ_COOKIE="${qq_cookie}" +youtube_key="$(uci_get_by_type "$NAME" "youtube_key")" +[ -n "${youtube_key}" ] && export YOUTUBE_KEY="${youtube_key}" + keep_core_when_upgrade="$(uci_get_by_type "$NAME" "keep_core_when_upgrade")" [ "$(uci_get_by_type "$NAME" "pub_access")" = "1" ] && addr="0.0.0.0" || addr="${lan_addr}" [ "$(uci_get_by_type "$NAME" "strict_mode")" = "1" ] && strict_mode="-s" @@ -61,8 +67,8 @@ set_ipset() { if [ "${set_type}" = "start" ]; then mkdir -p "/tmp/dnsmasq.d" - rm -f "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf" - cat <<-EOF > "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf" + rm -f "/tmp/dnsmasq.d/dnsmasq-$NAME.conf" + cat <<-EOF > "/tmp/dnsmasq.d/dnsmasq-$NAME.conf" dhcp-option=252,http://${lan_addr}:${http_port}/proxy.pac ipset=/.music.163.com/neteasemusic ipset=/interface.music.163.com/neteasemusic @@ -113,7 +119,7 @@ ipset=/clientlog3.music.163.com/neteasemusic [ -z "$(iptables -t "nat" -L "KOOLPROXY" | grep "UnblockMusic" | sed 's/\/.*//')" ] && iptables -t "nat" -I "KOOLPROXY" -m "set" --match-set "neteasemusic" "dst" -j "RETURN" -m "comment" --comment "KP for UnblockMusic" mkdir -p "/var/etc/" - echo "/etc/init.d/unblockneteasemusic restart" > "/var/etc/unblockneteasemusic.include" + echo "/etc/init.d/$NAME restart" > "/var/etc/$NAME.include" elif [ "${set_type}" = "stop" ]; then iptables -t "nat" -D "PREROUTING" -p "tcp" -m set --match-set "neteasemusic" "dst" -j "netease_cloud_music" iptables -t "nat" -D "KOOLPROXY" -m "set" --match-set "neteasemusic" "dst" -j "RETURN" -m "comment" --comment "KP for UnblockMusic" @@ -123,8 +129,8 @@ ipset=/clientlog3.music.163.com/neteasemusic ipset destroy "acl_neteasemusic_http" ipset destroy "acl_neteasemusic_https" - echo "" > "/var/etc/unblockneteasemusic.include" - rm -f "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf" + echo "" > "/var/etc/$NAME.include" + rm -f "/tmp/dnsmasq.d/dnsmasq-$NAME.conf" /etc/init.d/dnsmasq reload > "/dev/null" 2>&1 fi } @@ -133,8 +139,8 @@ set_hosts() { if [ "${set_type}" = "start" ]; then mkdir -p "/tmp/dnsmasq.d" - rm -f "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf" - cat <<-EOF > "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf" + rm -f "/tmp/dnsmasq.d/dnsmasq-$NAME.conf" + cat <<-EOF > "/tmp/dnsmasq.d/dnsmasq-$NAME.conf" dhcp-option=252,http://${lan_addr}:${http_port}/proxy.pac address=/music.163.com/${lan_addr} address=/interface.music.163.com/${lan_addr} @@ -149,7 +155,7 @@ address=/music.httpdns.c.163.com/0.0.0.0 ip route add "223.252.199.10" dev lo elif [ "${set_type}" = "stop" ]; then - rm -f "/tmp/dnsmasq.d/dnsmasq-unblockneteasemusic.conf" + rm -f "/tmp/dnsmasq.d/dnsmasq-$NAME.conf" /etc/init.d/dnsmasq reload > "/dev/null" 2>&1 ip route del "223.252.199.10" @@ -163,12 +169,12 @@ set_ports() iptables -I "INPUT" -p "tcp" --dport "${https_port}" -j "ACCEPT" mkdir -p "/var/etc/" - echo "/etc/init.d/unblockneteasemusic restart" > "/var/etc/unblockneteasemusic.include" + echo "/etc/init.d/$NAME restart" > "/var/etc/$NAME.include" elif [ "${set_type}" = "stop" ]; then iptables -D "INPUT" -p "tcp" --dport "${http_port}" -j "ACCEPT" iptables -D "INPUT" -p "tcp" --dport "${https_port}" -j "ACCEPT" - echo "" > "/var/etc/unblockneteasemusic.include" + echo "" > "/var/etc/$NAME.include" fi } @@ -186,6 +192,9 @@ start() [ ! -e "/usr/share/unblockneteasemusic/core/app.js" ] && { rm -f "/usr/share/unblockneteasemusic/local_ver"; bash "/usr/share/unblockneteasemusic/update.sh" "update_core_non_restart"; } [ ! -e "/usr/share/unblockneteasemusic/core/app.js" ] && { echo "Core Not Found, please download it before starting." >> "/tmp/unblockneteasemusic.log"; exit 1; } + [ "${use_remote_qq_server}" -ne "1" ] && qq_server_mode="local" || qq_server_mode="remote" + bash "/usr/share/unblockneteasemusic/gen_remote_qq_server.sh" "${qq_server_mode}" "${enable_flac}" > "/usr/share/unblockneteasemusic/core/src/provider/qq.js" + [ -n "${neteasemusic_cookie}" ] && { ub_cookie_line="$(sed -n -e "/netease.path.includes('song\/enhance')/=" "/usr/share/unblockneteasemusic/core/src/hook.js")"; [ -n "${ub_cookie_line}" ] && { let ub_cookie_endline="ub_cookie_line+6"; sed -i "${ub_cookie_line},${ub_cookie_endline}d" "/usr/share/unblockneteasemusic/core/src/hook.js"; } @@ -196,8 +205,6 @@ start() sed -i "/req.headers.cookie.replace(\/\\\s\\*MUSIC_\\\w=[^\\\s;]\\+/a\\\t\\t\\t\\t\\t].filter(line => line).join('; ')" "/usr/share/unblockneteasemusic/core/src/hook.js" sed -i "/].filter(line => line).join('; ')/a\\\t\\t\\t\\t}\\n" "/usr/share/unblockneteasemusic/core/src/hook.js" } - [ -n "${qq_cookie}" ] && un_env="${un_env} QQ_COOKIE=${qq_cookie}" - [ -n "${youtube_key}" ] && un_env="${un_env} YOUTUBE_KEY=${youtube_key}" quality_check_line="$(awk "/target == 0 \|\| item.id == target/{print NR}" "/usr/share/unblockneteasemusic/core/src/hook.js")" sed -i "${quality_check_line}d" "/usr/share/unblockneteasemusic/core/src/hook.js" @@ -213,15 +220,11 @@ start() sed -i -e "${quality_check_line}i \\\t\\tif (target == 0 || item.id == target) {" "/usr/share/unblockneteasemusic/core/src/hook.js" fi - { [ -f "${self_issue_cert_crt}" ] && [ "${self_issue_cert_crt}" != "/usr/share/unblockneteasemusic/core/server.crt" ]; } && { ln -sf "${self_issue_cert_crt}" "/usr/share/unblockneteasemusic/core/server.crt"; sed -i "/${self_issue_cert_crt//\//\\/}/d"; echo "${self_issue_cert_crt}" >> "/etc/sysupgrade.conf"; } - { [ -f "${self_issue_cert_key}" ] && [ "${self_issue_cert_key}" != "/usr/share/unblockneteasemusic/core/server.key" ]; } && { ln -sf "${self_issue_cert_key}" "/usr/share/unblockneteasemusic/core/server.key"; sed -i "/${self_issue_cert_key//\//\\/}/d"; echo "${self_issue_cert_key}" >> "/etc/sysupgrade.conf"; } + { [ -f "${self_issue_cert_crt}" ] && [ -f "${self_issue_cert_key}" ]; } && { ln -sf "${self_issue_cert_crt}" "/usr/share/unblockneteasemusic/core/server.crt"; ln -sf "${self_issue_cert_key}" "/usr/share/unblockneteasemusic/core/server.key"; } [ "${hijack_ways}" = "use_hosts" ] && { http_port="80"; https_port="443"; } - if [ "${music_source}" = "default" ]; then - nohup env ${un_env} node "/usr/share/unblockneteasemusic/core/app.js" -a "${addr}" -p "${http_port}":"${https_port}" -e "${endpoint_url}" ${netease_server_ip} ${proxy_server_ip} ${strict_mode} >> "/tmp/unblockneteasemusic.log" 2>&1 & - else - nohup env ${un_env} node "/usr/share/unblockneteasemusic/core/app.js" -a "${addr}" -p "${http_port}":"${https_port}" -o ${music_source} -e "${endpoint_url}" ${netease_server_ip} ${proxy_server_ip} ${strict_mode} >> "/tmp/unblockneteasemusic.log" 2>&1 & - fi + [ "${music_source}" = "default" ] && music_source="" || music_source="-o ${music_source}" + nohup node "/usr/share/unblockneteasemusic/core/app.js" -a "${addr}" -p "${http_port}":"${https_port}" ${music_source} -e "${endpoint_url}" ${netease_server_ip} ${proxy_server_ip} ${strict_mode} >> "/tmp/$NAME.log" 2>&1 & set_type="start" if [ "${hijack_ways}" = "use_ipset" ]; then @@ -229,7 +232,6 @@ start() elif [ "${hijack_ways}" = "use_hosts" ]; then set_hosts > "/dev/null" 2>&1 fi - [ "$(uci_get_by_type "$NAME" pub_access)" = "1" ] && set_ports > "/dev/null" 2>&1 } @@ -240,10 +242,13 @@ stop() sed -i '/unblockneteasemusic/d' "/etc/crontabs/root" /etc/init.d/cron restart > "/dev/null" 2>&1 - sed -i '/unblockneteasemusic\/core/d;/unblockneteasemusic\/local_ver/d' "/etc/sysupgrade.conf" - [ "${keep_core_when_upgrade}" -eq "1" ] && { echo "/usr/share/unblockneteasemusic/core/" >> "/etc/sysupgrade.conf"; echo "/usr/share/unblockneteasemusic/local_ver" >> "/etc/sysupgrade.conf"; } + [ ! -f "${UPGRADE_CONF}" ] && touch "${UPGRADE_CONF}" + sed -i '/unblockneteasemusic\/core/d;/unblockneteasemusic\/local_ver/d' "${UPGRADE_CONF}" + [ "${keep_core_when_upgrade}" -eq "1" ] && { echo "/usr/share/unblockneteasemusic/core/" >> "${UPGRADE_CONF}"; echo "/usr/share/unblockneteasemusic/local_ver" >> "${UPGRADE_CONF}"; } + [ -f "${self_issue_cert_crt}" ] && { sed -i "/${self_issue_cert_crt//\//\\/}/d"; echo "${self_issue_cert_crt}" >> "${UPGRADE_CONF}"; } + [ -f "${self_issue_cert_key}" ] && { sed -i "/${self_issue_cert_key//\//\\/}/d"; echo "${self_issue_cert_key}" >> "${UPGRADE_CONF}"; } - rm -f "/tmp/unblockneteasemusic.log" + rm -f "/tmp/$NAME.log" set_type="stop" set_ipset > "/dev/null" 2>&1 diff --git a/package/ctcgfw/luci-app-unblockneteasemusic/root/usr/share/unblockneteasemusic/gen_remote_qq_server.sh b/package/ctcgfw/luci-app-unblockneteasemusic/root/usr/share/unblockneteasemusic/gen_remote_qq_server.sh new file mode 100755 index 0000000000..c015762317 --- /dev/null +++ b/package/ctcgfw/luci-app-unblockneteasemusic/root/usr/share/unblockneteasemusic/gen_remote_qq_server.sh @@ -0,0 +1,182 @@ +#!/bin/bash +# Created By [CTCGFW]Project OpenWRT +# https://github.com/project-openwrt + +if [ "$1" == "local" ] +then echo -e "// local_mode +const cache = require('../cache') +const insure = require('./insure') +const select = require('./select') +const request = require('../request') + +const headers = { + 'origin': 'http://y.qq.com/', + 'referer': 'http://y.qq.com/', + 'cookie': process.env.QQ_COOKIE || null // 'uin=; qm_keyst=', +} + +const playable = song => { + const switchFlag = song['switch'].toString(2).split('') + switchFlag.pop() + switchFlag.reverse() + const playFlag = switchFlag[0] + const tryFlag = switchFlag[13] + return ((playFlag == 1) || ((playFlag == 1) && (tryFlag == 1))) +} + +const format = song => ({ + id: {song: song.mid, file: song.file.media_mid}, + name: song.name, + duration: song.interval * 1000, + album: {id: song.album.mid, name: song.album.name}, + artists: song.singer.map(({mid, name}) => ({id: mid, name})) +}) + +const search = info => { + const url = + 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp?' + + 'ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.center&' + + 't=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=20&w=' + encodeURIComponent(info.keyword) + '&' + + 'g_tk=5381&jsonpCallback=MusicJsonCallback10005317669353331&loginUin=0&hostUin=0&' + + 'format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0' + + return request('GET', url) + .then(response => response.jsonp()) + .then(jsonBody => { + const list = jsonBody.data.song.list.map(format) + const matched = select(list, info) + return matched ? matched.id : Promise.reject() + }) +} + +const single = (id, format) => { + const uin = ((headers.cookie || '').match(/uin=(\d+)/) || [])[1] || '0' + + const concatenate = vkey => { + if (!vkey) return Promise.reject() + const host = ['streamoc.music.tc.qq.com', 'mobileoc.music.tc.qq.com', 'isure.stream.qqmusic.qq.com', 'dl.stream.qqmusic.qq.com', 'aqqmusic.tc.qq.com/amobile.music.tc.qq.com'][3] + return \`http://\${host}/\${format.join(id.file)}?vkey=\${vkey}&uin=0&fromtag=8&guid=7332953645\` + } + + const url = + 'https://u.y.qq.com/cgi-bin/musicu.fcg?data=' + + encodeURIComponent(JSON.stringify({ + req_0: { + module: 'vkey.GetVkeyServer', + method: 'CgiGetVkey', + param: { + guid: '7332953645', + loginflag: 1, + filename: [format.join(id.file)], + songmid: [id.song], + songtype: [0], + uin, + platform: '20' + } + } + })) + + return request('GET', url, headers) + .then(response => response.json()) + .then(jsonBody => { + const { sip, midurlinfo } = jsonBody.req_0.data + return midurlinfo[0].purl ? sip[0] + midurlinfo[0].purl : Promise.reject() + }) +} + +const track = id => { + id.key = id.file + return Promise.all( + [['F000', '.flac'], ['M800', '.mp3'], ['M500', '.mp3']].slice((headers.cookie || typeof(window) !== 'undefined') ? (select.ENABLE_FLAC ? 0 : 1) : 2) + .map(format => single(id, format).catch(() => null)) + ) + .then(result => result.find(url => url) || Promise.reject()) + .catch(() => insure().qq.track(id)) +} + +const check = info => cache(search, info).then(track) + +module.exports = {check, track}" +elif [ "$1" == "remote" ] +then [ "$2" == "1" ] && { flac_quality="'flac', "; loop_times="4"; } || loop_times="3" +echo -e "// remote_mode +const cache = require('../cache') +const insure = require('./insure') +const select = require('./select') +const request = require('../request') + +const headers = { + 'origin': 'http://y.qq.com/', + 'referer': 'http://y.qq.com/', + 'cookie': null +} + +const playable = song => { + const switchFlag = song['switch'].toString(2).split('') + switchFlag.pop() + switchFlag.reverse() + const playFlag = switchFlag[0] + const tryFlag = switchFlag[13] + return ((playFlag == 1) || ((playFlag == 1) && (tryFlag == 1))) +} + +const format = song => ({ + id: {song: song.mid, file: song.file.media_mid}, + name: song.name, + duration: song.interval * 1000, + album: {id: song.album.mid, name: song.album.name}, + artists: song.singer.map(({mid, name}) => ({id: mid, name})) +}) + +const search = info => { + const url = + 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp?' + + 'ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.center&' + + 't=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=20&w=' + + encodeURIComponent(info.keyword) + '&' + + 'g_tk=5381&jsonpCallback=MusicJsonCallback10005317669353331&loginUin=0&hostUin=0&' + + 'format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0' + + return request('GET', url) + .then(response => response.jsonp()) + .then(jsonBody => { + const list = jsonBody.data.song.list.map(format) + const matched = select(list, info) + return matched ? matched.id : Promise.reject() + }) +} + +const track = id => { + const typeObj = [${flac_quality}'320', '128', 'm4a'] + + let i = 0 + while (i < ${loop_times}) { + type = typeObj[i] + let url = + 'https://api.qq.jsososo.com/song/url?id=' + + id.song + '&mediaId=' + id.file + '&type=' + \`\${type}\` + + return request('GET', url) + .then(response => response.json()) + .then(jsonBody => { + let res = jsonBody.result + if (res === 100) { + let songUrl = jsonBody.data + return songUrl + } else if (i === 3) { + return Promise.reject() + } else { + return + } + }) + .catch(() => insure().qq.track(id)) + i++ + } +} + +const check = info => cache(search, info).then(track) + +module.exports = {check, track}" +else echo -e "Usage: $0 [local|remote] (1)" +fi