This commit is contained in:
72
XiaMiPlayer/Action.php
Normal file
72
XiaMiPlayer/Action.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
if(!defined('__TYPECHO_ROOT_DIR__'))exit;
|
||||
class XiaMiPlayer_Action extends Typecho_Widget implements Widget_Interface_Do {
|
||||
public function execute(){}
|
||||
public function action(){
|
||||
$this->on($this->request->isGet())->player();
|
||||
}
|
||||
|
||||
private function player(){
|
||||
$dir = Typecho_Widget::widget('Widget_Options')->pluginUrl;
|
||||
error_reporting(0);
|
||||
header('content-type: application/javascript');
|
||||
if(!isset($_GET['songs'])) $_GET['songs'] = '';
|
||||
$gets = explode(",", $_GET['songs']);
|
||||
$songs = array();
|
||||
foreach($gets as $get) {
|
||||
$songs[] = strstr($get, '|') ? array_combine(array('url', 'name'), explode('|', $get)) : $get;
|
||||
}
|
||||
|
||||
$cuz = '';
|
||||
if (isset($_GET['setting'])) {
|
||||
$gets = explode(',', $_GET['setting']);
|
||||
$setting = array('background'=>'#'.$gets[0], 'border-bottom'=>'#'.$gets[1]);
|
||||
$cuz = '
|
||||
playbox.css('.json_encode($setting).');
|
||||
$(".box", playbox).css('.json_encode($setting).');
|
||||
$(".progress", playbox).css("background", "'.$setting['border-bottom'].'");';
|
||||
}
|
||||
$code = json_encode($songs);
|
||||
|
||||
echo
|
||||
<<<EOF
|
||||
(function($, songs) {
|
||||
api = '$dir/XiaMiPlayer/ajax.php?type=songs&id=';
|
||||
time = new Date().getTime();
|
||||
document.write('<div id="'+time+'" class="xiamiplayer"><div class="box"><div class="progress"></div><div class="play"></div><div class="btn-play"></div><span></span></div><ul class="list"></ul></div>');
|
||||
playbox = $('#'+time);
|
||||
(function(playbox) {
|
||||
songs.forEach(function(song, i) {
|
||||
var li = $('<li></li>');
|
||||
if(typeof song != 'object') {
|
||||
li.attr('data-xiami', '1'),
|
||||
li.attr('data-id', song);
|
||||
$.getJSON(api+song, function(res) {
|
||||
li.attr('data-url', res.listen_file),
|
||||
li.attr('data-name', res.song_name),
|
||||
li.attr('data-artist', res.artist_name),
|
||||
li.attr('data-lyric', res.lyric),
|
||||
li.text([res.song_name, res.artist_name].join(' - '));
|
||||
if(i===0) {
|
||||
console.log('Init music id '+song+' for playbox id #'+playbox.attr('id'));
|
||||
XiaMiPlayerInit(li, playbox, false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
li.attr('data-xiami', '0'),
|
||||
li.attr('data-url', song.url),
|
||||
li.text(song.name);
|
||||
if(i===0) XiaMiPlayerInit(li, playbox, false);
|
||||
}
|
||||
$('.list', playbox).append(li);
|
||||
})
|
||||
})(playbox);
|
||||
|
||||
if(songs.length <= 1)
|
||||
$('.list', playbox).addClass('display');
|
||||
|
||||
$cuz
|
||||
})(jQuery, $code);
|
||||
EOF;
|
||||
}
|
||||
}
|
||||
492
XiaMiPlayer/Plugin.php
Normal file
492
XiaMiPlayer/Plugin.php
Normal file
@@ -0,0 +1,492 @@
|
||||
<?php
|
||||
/**
|
||||
* 虾米音乐播放器:虾米音乐搜索+引用
|
||||
*
|
||||
* @package XiaMiPlayer
|
||||
* @author 公子
|
||||
* @version 3.1.4
|
||||
* @link https://imnerd.org
|
||||
*/
|
||||
class XiaMiPlayer_Plugin implements Typecho_Plugin_Interface
|
||||
{
|
||||
/**
|
||||
* 激活插件方法,如果激活失败,直接抛出异常
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @throws Typecho_Plugin_Exception
|
||||
*/
|
||||
public static Function activate()
|
||||
{
|
||||
Helper::addRoute("XiaMiPlayer_Route","/XiaMiPlayer","XiaMiPlayer_Action",'action');
|
||||
Typecho_Plugin::factory('admin/write-post.php')->bottom = array('XiaMiPlayer_Plugin', 'Insert');
|
||||
Typecho_Plugin::factory('admin/write-page.php')->bottom = array('XiaMiPlayer_Plugin', 'Insert');
|
||||
Typecho_Plugin::factory('Widget_Archive')->header = array('XiaMiPlayer_Plugin', 'header');
|
||||
Typecho_Plugin::factory('Widget_Abstract_Contents')->contentEx = array('XiaMiPlayer_Plugin','ParseXiaMi');
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用插件方法,如果禁用失败,直接抛出异常
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
* @throws Typecho_Plugin_Exception
|
||||
*/
|
||||
public static function deactivate(){
|
||||
Helper::removeRoute("XiaMiPlayer_Route");
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件的实现方法
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function header()
|
||||
{
|
||||
$options = Helper::options();
|
||||
if($options->plugin('XiaMiPlayer')->jquery) {
|
||||
echo "<script type=\"text/javascript\" src=\"//lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js\"></script>";
|
||||
}
|
||||
?>
|
||||
<link rel="stylesheet" type="text/css" href="<?php $options->pluginUrl('XiaMiPlayer/jplayer/XiaMiPlayer.css'); ?>" />
|
||||
<script type="text/javascript" src="<?php $options->pluginUrl('XiaMiPlayer/jplayer/jquery.jplayer.min.js'); ?>"></script>
|
||||
<?php
|
||||
|
||||
?>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件的实现方法
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function Insert()
|
||||
{
|
||||
$options = Helper::options();
|
||||
$config = $options->plugin('XiaMiPlayer');
|
||||
$box = Typecho_Common::url('XiaMiPlayer/jplayer/index.html', $options->pluginUrl);
|
||||
$music = Typecho_Common::url('XiaMiPlayer',$options->index);
|
||||
$ajax = $options->pluginUrl.'/XiaMiPlayer/ajax.php';
|
||||
/* 播放器样式 */
|
||||
switch($config->type) {
|
||||
case 'blue':
|
||||
$color = '37839e,2b5c70';
|
||||
break;
|
||||
case 'green':
|
||||
$color = '74db89,55db74';
|
||||
break;
|
||||
case 'yellow':
|
||||
$color = 'ffd863,de8d24';
|
||||
break;
|
||||
case 'red':
|
||||
$color = 'd64e3c,b82a25';
|
||||
break;
|
||||
case 'purple':
|
||||
$color = '8073c7,5c396e';
|
||||
break;
|
||||
case 'user':
|
||||
$color = ($config->background && $config->border) ? ','.substr($config->background,1).'|'.substr($config->border,1) : '';
|
||||
break;
|
||||
default:
|
||||
$color = '';
|
||||
break;
|
||||
}
|
||||
?>
|
||||
<link rel="stylesheet" type="text/css" href="<?php $options->pluginUrl('XiaMiPlayer/jplayer/XiaMiPlayer.css'); ?>" />
|
||||
<link rel="stylesheet" type="text/css" href="<?php echo Typecho_Common::url('XiaMiPlayer/style.css' , $options->pluginUrl); ?>" />
|
||||
<script type="text/javascript" src="<?php $options->pluginUrl('XiaMiPlayer/jplayer/jquery.jplayer.min.js'); ?>"></script>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
/* 判断是否为默认编辑器插入音乐按钮 */
|
||||
if($('#wmd-button-row').length>0) {
|
||||
$('#wmd-button-row').prepend('<li class="wmd-button" id="wmd-music-button" style="" title="插入音乐 Ctrl + Shift + M">♫</li>');
|
||||
} else {
|
||||
$('#text').before('<a href="javascript:void(0)" id="wmd-music-button" title="插入音乐 Ctrl + Shift + M">插入歌曲</a>');
|
||||
}
|
||||
|
||||
/* 为编辑器按钮增加点击事件 */
|
||||
$(document).on('click', '#wmd-music-button', function() {
|
||||
$('body').append('<div id="searchPanel">'+
|
||||
'<div class="wmd-prompt-background" style="height:'+$(document).height()+'px;width:'+$(document).width()+'px;"></div>'+
|
||||
'<div class="wmd-prompt-dialog">'+
|
||||
'<div>'+
|
||||
'<ul id="tab" class="wmd-button-row">'+
|
||||
'<li onclick="xm_search();" title="Ctrl + ←"><b>虾米搜索</b></li>'+
|
||||
'<li onclick="xm_link();" title="Ctrl + →"><b>输入链接</b></li>'+
|
||||
'<li class="multi" data="0" onclick="multi();">[列表]</li>'+
|
||||
'</ul>'+
|
||||
'<div class=\"close\" onclick=\"rm();\" title="Esc">×</div>'+
|
||||
'</div>'+
|
||||
'<form id="xm"></form>'+
|
||||
'</div>'+
|
||||
'</div>');
|
||||
xm_search();
|
||||
});
|
||||
|
||||
/* 增加各种快捷键操作 */
|
||||
$(document).on('keydown', function(e){
|
||||
|
||||
/* Ctrl+Shift+M 调出音乐搜索窗口 */
|
||||
if(e.ctrlKey && e.shiftKey && e.keyCode == '77')
|
||||
$('#wmd-music-button').click();
|
||||
|
||||
/* ESC 退出音乐搜索窗口 */
|
||||
if(($('#searchPanel').length != 0) && e.keyCode == '27')
|
||||
rm();
|
||||
|
||||
/* Ctrl+Enter 执行搜索操作 */
|
||||
if($('#xiami_search').is(':focus') && $('#xiami_search').val() != '' && e.ctrlKey && e.keyCode == '13') {
|
||||
$('#xiami_navi').attr('page','1');
|
||||
search();
|
||||
}
|
||||
|
||||
/* Ctrl+Pagedown 下一页 */
|
||||
if(e.ctrlKey && e.keyCode == '40') {
|
||||
next();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
/*Ctrl+Pageup 上一页 */
|
||||
if(e.ctrlKey && e.keyCode == '38') {
|
||||
pre();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
/*Ctrl+Left 调出虾米搜索窗口 */
|
||||
if(e.ctrlKey && e.keyCode == '37') {
|
||||
xm_search();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
/*Ctrl+Right 调出直链窗口 */
|
||||
if(e.ctrlKey && e.keyCode == '39') {
|
||||
xm_link();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
/*Ctrl+[1-8] 使用数字键快捷选择歌曲 */
|
||||
for(var i=1;i<9;i++) {
|
||||
var result = $('#xiami_result a');
|
||||
if(($('#searchPanel').length != 0) && result[i-1] != null && parseInt(e.keyCode) == 48+i) {
|
||||
$(result[i-1]).click();
|
||||
$('#text').focus();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function multi() {
|
||||
var multi = $('.multi');
|
||||
if(multi.hasClass('checked')){
|
||||
multi.removeClass('checked');
|
||||
multi.attr('data', '0');
|
||||
$('.multibtn').remove();
|
||||
$('#playlist').remove();
|
||||
} else {
|
||||
multi.addClass('checked');
|
||||
multi.attr('data', '1');
|
||||
multi.after('<button class="multibtn" onclick="multishow()">确定</button>');
|
||||
$('#tab').after('<ul id="playlist"></ul>');
|
||||
}
|
||||
}
|
||||
|
||||
function multishow() {
|
||||
var list = $('#playlist li');
|
||||
if(list.length == 0) return false;
|
||||
var ids = [].slice.call(list).map(function(item) {
|
||||
return item.getAttribute('data-url') ? item.getAttribute('data-url')+'|'+item.innerHTML : item.getAttribute('data-id');
|
||||
});
|
||||
var c = '<script type="text/javascript" src="<?php echo $music; ?>?songs='+ids.join(',')+'<?php if($color) echo "&setting=$color"; ?>"><\/script>';
|
||||
$('#text').val($('#text').val() + c);
|
||||
editor(c);
|
||||
rm();
|
||||
}
|
||||
|
||||
function xm_search() {
|
||||
$('#xm').html('<form>'+
|
||||
'<input type=\"text\" id=\"xiami_search\" autocomplete=\"off\">'+
|
||||
'<input type=\"hidden\" id=\"xiami_page\" value=\"1\">'+
|
||||
'<div class="btn-s primary" onclick=\"$(\'#xiami_navi\').attr(\'page\',\'1\');search();\" style="float:right;padding:0 12px;line-height:28px;" title="Ctrl + Enter">搜索</div>'+
|
||||
'</form>'+
|
||||
'<br style="clear:both;" />'+
|
||||
'<div id=\"xiami_list\">'+
|
||||
'<div id=\"xiami_result\"></div>'+
|
||||
'<div id=\"xiami_navi\" page="1">'+
|
||||
'<a href="#" class="pre" onclick="pre();" title="Ctrl+↑" style="display:inline-table;border:none;float:left;"></a>'+
|
||||
'<a href="#" class="next" onclick="next();" title="Ctrl+↓" style="display:inline-table;border:none;float:right;"></a>'+
|
||||
'</div>');
|
||||
$('#xiami_search').focus();
|
||||
}
|
||||
|
||||
function xm_link() {
|
||||
$('#xm').html('<p style="margin-bottom:15px;">输入歌曲名称和歌曲直链地址,其中歌曲名称选填。</p>'+
|
||||
'<p><input type=\"text\" id=\"song_name\" placeholder="歌曲名称"></p>'+
|
||||
'<p><input type=\"text\" id=\"song_link\" placeholder="歌曲地址"></p>'+
|
||||
'<button class="btn-s primary" onclick=\"insert_link();return false;\">插入</button>');
|
||||
$('#song_name').focus();
|
||||
}
|
||||
|
||||
function pre() {
|
||||
var n = $('#xiami_navi'), p = Number(n.attr('page'))-1;
|
||||
if(p == 1) $('.pre').html('');
|
||||
n.attr('page', p);
|
||||
search();
|
||||
}
|
||||
|
||||
function next() {
|
||||
var n = $('#xiami_navi'), p = Number(n.attr('page'))+1;
|
||||
n.attr('page', p);
|
||||
search();
|
||||
}
|
||||
|
||||
function search() {
|
||||
var k = $('#xiami_search').val(), p = Number($('#xiami_navi').attr('page'));
|
||||
$('.pre').html('上一页');
|
||||
$('.next').html('下一页');
|
||||
if(k) {
|
||||
$('#xiami_result').html('正在载入请稍后...');
|
||||
$.getJSON('<?php echo $ajax; ?>?type=search&id='+k+'&page='+p,function(data) {
|
||||
$('#xiami_result').html('');
|
||||
$.each(data.songs,
|
||||
function(i, item) {
|
||||
var name = decodeURIComponent(item.song_name).replace('+', ' '), artist = decodeURIComponent(item.artist_name).split('+').join(' ');
|
||||
$('<a href=\"#\" onclick=\"show(\'' + item.song_id + '\',\'' + name.replace('\'', '\\\'').replace(/(\r)?\n/g, '') + '-' + artist.replace('\'', '\\\'').replace(/(\r)?\n/g, '') + '\');\" title=\"Ctrl + '+(i+1)+'\">' + (i+1) + '. ' + name + ' - ' + artist + '</a>').appendTo('#xiami_result');
|
||||
});
|
||||
});
|
||||
} else {
|
||||
alert('请输入歌曲名称!')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function rm() {$('#searchPanel').remove()}
|
||||
|
||||
function show(id, name) {
|
||||
if($('ul#playlist').size()>0) {
|
||||
if($('ul#playlist li[data-id="'+id+'"]').size()>0)
|
||||
alert('《'+name+'》已经被添加到列表中了!');
|
||||
else
|
||||
$('ul#playlist').append('<li data-id="'+id+'">'+name+'</li>');
|
||||
} else {
|
||||
var c = '[xiami <?php echo $music; ?>?songs='+id+'<?php if($color) echo "&setting=$color"; ?>]';
|
||||
editor(c);
|
||||
rm();
|
||||
}
|
||||
}
|
||||
|
||||
function insert_link() {
|
||||
if($('#song_link').val()=='') return alert('必须输入音乐链接');
|
||||
var name = $('#song_name').val(), link = $('#song_link').val();
|
||||
if($('ul#playlist').size()>0) {
|
||||
if($('ul#playlist li[data-url="'+link+'"]').size()>0)
|
||||
alert('《'+name+'》已经被添加到列表中了!');
|
||||
else
|
||||
$('ul#playlist').append('<li data-url="'+link+'">'+name+'</li>');
|
||||
} else {
|
||||
var c = '[xiami <?php echo $music; ?>?songs='+link+'|'+name+'<?php if($color) echo "&setting=$color"; ?>]';
|
||||
editor(c);
|
||||
rm();
|
||||
}
|
||||
}
|
||||
|
||||
function editor(c) {
|
||||
var textarea = $('#text'),
|
||||
sel = textarea.getSelection(),
|
||||
offset = (sel ? sel.start : 0)+c.length;
|
||||
textarea.replaceSelection(c);
|
||||
textarea.setSelection(offset,offset);
|
||||
if (window.frames.length > 0) {
|
||||
if (fck = window.frames['text___Frame'])
|
||||
var _c = fck.document.getElementsByTagName('iframe')[0].contentDocument.body;
|
||||
|
||||
else if (mce = window.frames['text_ifr'])
|
||||
var _c = mce.document.body;
|
||||
|
||||
else if (kin = document.getElementsByClassName('ke-edit-iframe')[0])
|
||||
var _c = kin.contentDocument.body;
|
||||
|
||||
else if (cke = document.getElementsByClassName('cke_wysiwyg_frame')[0])
|
||||
var _c = cke.contentDocument.body;
|
||||
|
||||
_c.innerHTML = _c.innerHTML + c;
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on('mousedown', '#playlist', function(e) {
|
||||
document.onselectstart = function(){return false;}
|
||||
$('body').addClass('select');
|
||||
|
||||
var ul = $(this), li = $('#playlist li'),limit = {
|
||||
up:parseInt(ul.offset().top),
|
||||
down:parseInt(li.last().offset().top),
|
||||
left:parseInt(ul.offset().left),
|
||||
right:parseInt(ul.offset().left)+ul.width()
|
||||
},height = [],parent=parseInt(ul.offsetParent().offset().top);
|
||||
for(var i=0,l=li.length;i<l;i++) height.push(li[i].offsetTop+parent);
|
||||
var t = $(e.target), s = $(document.createElement('li'));
|
||||
s.addClass('sortable');
|
||||
$('.sortable').remove(), t.before(s);
|
||||
t.addClass('hover');
|
||||
$(document).on('mousemove', function(e) {
|
||||
var top = e.pageY;
|
||||
if(top<limit.up) {
|
||||
//top = limit.up;
|
||||
ul.prepend(s);
|
||||
} else if (top>limit.down) {
|
||||
//top = limit.down;
|
||||
ul.append(s);
|
||||
} else {
|
||||
t.css({'top':(top-ul.offsetParent().offset().top)+'px','left':(e.pageX-ul.offsetParent().offset().left)+'px'});
|
||||
var f = $(li[getIndex(top)]);
|
||||
if(!$(f.siblings()[0]).hasClass('sortable')) f.before(s);
|
||||
}
|
||||
});
|
||||
$(document).on('mouseup', function(e) {
|
||||
$(document).off('mouseup');
|
||||
$(document).off('mousemove');
|
||||
document.onselectstart = function(){return true;}
|
||||
$('body').removeClass('select');
|
||||
var left = e.pageX;
|
||||
left>limit.right || left<limit.left ? t.remove() : s.before(t);
|
||||
s.remove();
|
||||
t.removeClass('hover');
|
||||
});
|
||||
function getIndex(y) {
|
||||
var i=0;
|
||||
height.forEach(function(value, index){
|
||||
if(y >= value){i=index+1;return true;}
|
||||
});
|
||||
return i;
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析文章中出现的专辑和精选集链接
|
||||
*
|
||||
* @access public
|
||||
* @return 文章内容 $content
|
||||
*/
|
||||
public static function ParseXiaMi($content, $widget, $lastResult) {
|
||||
$content = empty($lastResult) ? $content : $lastResult;
|
||||
/* 播放器样式 */
|
||||
$options = Helper::options();
|
||||
$url = Typecho_Common::url('XiaMiPlayer',$options->index);
|
||||
$ajax = $options->pluginUrl.'/XiaMiPlayer/ajax.php';
|
||||
$config = $options->plugin('XiaMiPlayer');
|
||||
switch($config->type) {
|
||||
case 'blue':
|
||||
$color = '37839e,2b5c70';
|
||||
break;
|
||||
case 'green':
|
||||
$color = '74db89,55db74';
|
||||
break;
|
||||
case 'yellow':
|
||||
$color = 'ffd863,de8d24';
|
||||
break;
|
||||
case 'red':
|
||||
$color = 'd64e3c,b82a25';
|
||||
break;
|
||||
case 'purple':
|
||||
$color = '8073c7,5c396e';
|
||||
break;
|
||||
case 'user':
|
||||
$color = ($config->background && $config->border) ? ','.substr($config->background,1).'|'.substr($config->border,1) : '';
|
||||
break;
|
||||
default:
|
||||
$color = '';
|
||||
break;
|
||||
}
|
||||
/** 短代码替换 **/
|
||||
$number = preg_match_all('/\[xiami (.*?)\]/si', $content, $match);
|
||||
if($number) {foreach($match[0] as $key => $string) {
|
||||
$content = str_replace($string, '<script type="text/javascript" src="'.strip_tags($match[1][$key]).'"></script>', $content);
|
||||
}}
|
||||
|
||||
/** Markdown替换 **/
|
||||
$number = preg_match_all("/<a href=\"(https:\/\/(www.)?xiami\.com\/([a-z]+)\/([a-zA-Z0-9]+))\">\\1<\/a>/im", $content, $match);
|
||||
if($number) {foreach($match[0] as $key => $string) {
|
||||
$type = $match[3][$key]=='song' ? 'songs' : $match[3][$key];
|
||||
$id = $match[4][$key];
|
||||
$result = json_decode(file_get_contents($ajax.'?type='.$type.'&id='.$id), true);
|
||||
if(in_array($type, array("album", "collect"))) {
|
||||
if(empty($result['songs'])) continue;
|
||||
$songs = array();
|
||||
foreach($result['songs'] as $song) $songs[] = $song['song_id'];
|
||||
$lurl = $url."?songs=".implode(',', $songs);
|
||||
if($color) $lurl .= "&setting=$color";
|
||||
$content = str_replace($string, '<script type="text/javascript" src="'.$lurl.'"></script>', $content);
|
||||
} else {
|
||||
if(!$result['song_id']) continue;
|
||||
$surl = $url."?songs=".$result['song_id'];
|
||||
if($color) $surl .= "&setting=$color";
|
||||
$content = str_replace($string, '<script type="text/javascript" src="'.$surl.'"></script>', $content);
|
||||
}
|
||||
}}
|
||||
|
||||
/** 非Markdown替换 **/
|
||||
$number = preg_match_all("/https:\/\/(www.)?xiami\.com\/([a-z]+)\/([a-zA-Z0-9]+)/im", $content, $match);
|
||||
if($number) {foreach($match[0] as $key => $string) {
|
||||
$type = $match[2][$key]=='song' ? 'songs' : $match[2][$key];
|
||||
$id = $match[3][$key];
|
||||
$result = json_decode(file_get_contents($ajax.'?type='.$type.'&id='.$id), true);
|
||||
if(in_array($type, array("album", "collect"))) {
|
||||
if(empty($result['songs'])) continue;
|
||||
$songs = array();
|
||||
foreach($result['songs'] as $song) $songs[] = $song['song_id'];
|
||||
$lurl = $url."?songs=".implode(',', $songs);
|
||||
if($color) $lurl .= "&setting=$color";
|
||||
$content = str_replace($string, '<script type="text/javascript" src="'.$lurl.'"></script>', $content);
|
||||
} else {
|
||||
if(!$result['song_id']) continue;
|
||||
$surl = $url."?songs=".$result['song_id'];
|
||||
if($color) $surl .= "&setting=$color";
|
||||
$content = str_replace($string, '<script type="text/javascript" src="'.$surl.'"></script>', $content);
|
||||
}
|
||||
}}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件配置面板
|
||||
*
|
||||
* @access public
|
||||
* @param Typecho_Widget_Helper_Form $form 配置面板
|
||||
* @return void
|
||||
*/
|
||||
public static function config(Typecho_Widget_Helper_Form $form)
|
||||
{
|
||||
$jquery = new Typecho_Widget_Helper_Form_Element_Radio('jquery', array('0' => _t('不加载'), '1' => _t('加载')), '1', _t('是否加载外部jQuery库文件'), _t('插件需要jQuery库文件的支持,如果主题已经加载了可以选择不加载'));
|
||||
$form->addInput($jquery);
|
||||
|
||||
$color = array('orange' => _t('默认橙'),'blue' => _t('天空蓝'),'green' => _t('自然绿'),'yellow' => _t('大地黄'),'red' => _t('高原红'),'purple' => _t('葡萄紫'),'user' => _t('自定义'));
|
||||
$type = new Typecho_Widget_Helper_Form_Element_Radio('type', $color,'orange',_t('请选择播放器样式'));
|
||||
$form->addInput($type);
|
||||
|
||||
$background = new Typecho_Widget_Helper_Form_Element_Text('background', NULL, '#FF6503', _t('播放器背景'), NULL);
|
||||
$background->input->setAttribute('class', 'mini');
|
||||
$form->addInput($background);
|
||||
|
||||
$border = new Typecho_Widget_Helper_Form_Element_Text('border', NULL, '#C4753D', _t('播放器边框'), NULL);
|
||||
$border->input->setAttribute('class', 'mini');
|
||||
$form->addInput($border);
|
||||
}
|
||||
|
||||
/**
|
||||
* 个人用户的配置面板
|
||||
*
|
||||
* @access public
|
||||
* @param Typecho_Widget_Helper_Form $form
|
||||
* @return void
|
||||
*/
|
||||
public static function personalConfig(Typecho_Widget_Helper_Form $form){}
|
||||
|
||||
}
|
||||
15
XiaMiPlayer/README.md
Normal file
15
XiaMiPlayer/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
### 迷你版虾米点播插件XiaMiPlayer v3.1.4
|
||||
|
||||
通过编辑器按钮在线搜索虾米歌曲或输入mp3链接组成列表插入文章,采用jplayer迷你多彩播放器,支持快捷键。
|
||||
|
||||
:warning:由于原服务端lyric.php缺失暂时无法显示歌词。
|
||||
|
||||
- v3.1.4(18-7-25):([@羽中](https://github.com/jzwalk))
|
||||
使用短代码替换兼容Typecho1.1+版Markdown解析,修正虾米地址自动替换和编辑区焦点定位等问题。
|
||||
|
||||
- v3.1.3复活版(17-2-16):
|
||||
整合[XiamiMusicAPI](https://github.com/metowolf/XiamiMusicAPI)内置action调用核心功能。
|
||||
|
||||
- 补更至v3.1.2。
|
||||
|
||||
###### 更多详见作者博客:http://imnerd.org/XiaMiPlayer-Plugin-for-typecho-0-9.html
|
||||
96
XiaMiPlayer/XiamiMusicAPI.php
Normal file
96
XiaMiPlayer/XiamiMusicAPI.php
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/*!
|
||||
* Xiami Music Api
|
||||
* https://i-meto.com
|
||||
* Version 0.1.0 beta
|
||||
*
|
||||
* Copyright 2016, METO
|
||||
* Released under the MIT license
|
||||
*/
|
||||
class XiamiMusicAPI{
|
||||
// General
|
||||
protected $_USERAGENT='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36';
|
||||
protected $_COOKIE='user_from=2;XMPLAYER_addSongsToggler=0;XMPLAYER_isOpen=0;_xiamitoken=cb8bfadfe130abdbf5e2282c30f0b39a;';
|
||||
protected $_REFERER='http://h.xiami.com/';
|
||||
// CURL
|
||||
protected function curl($url,$data=null){
|
||||
$curl=curl_init();
|
||||
curl_setopt($curl,CURLOPT_URL,$url);
|
||||
if($data){
|
||||
if(is_array($data))$data=http_build_query($data);
|
||||
curl_setopt($curl,CURLOPT_POSTFIELDS,$data);
|
||||
curl_setopt($curl,CURLOPT_POST,1);
|
||||
}
|
||||
curl_setopt($curl,CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl,CURLOPT_CONNECTTIMEOUT, 10);
|
||||
curl_setopt($curl,CURLOPT_REFERER,$this->_REFERER);
|
||||
curl_setopt($curl,CURLOPT_COOKIE,$this->_COOKIE);
|
||||
curl_setopt($curl,CURLOPT_USERAGENT,$this->_USERAGENT);
|
||||
$result=curl_exec($curl);
|
||||
curl_close($curl);
|
||||
return $result;
|
||||
}
|
||||
// main function
|
||||
public function search($s,$limit=30,$offset=0,$type=1){
|
||||
$url='http://api.xiami.com/web?';
|
||||
$data=array(
|
||||
'v'=>'2.0',
|
||||
'app_key'=>'1',
|
||||
'key'=>$s,
|
||||
'page'=>($offset+1),
|
||||
'limit'=>$limit,
|
||||
'r'=>'search/songs',
|
||||
);
|
||||
return $this->curl($url.http_build_query($data));
|
||||
}
|
||||
public function artist($artist_id){
|
||||
$url='http://api.xiami.com/web?';
|
||||
$data=array(
|
||||
'v'=>'2.0',
|
||||
'app_key'=>'1',
|
||||
'id'=>$artist_id,
|
||||
'page'=>1,
|
||||
'limit'=>30,
|
||||
'r'=>'artist/hot-songs',
|
||||
);
|
||||
return $this->curl($url.http_build_query($data));
|
||||
}
|
||||
public function album($album_id){
|
||||
$url='http://api.xiami.com/web?';
|
||||
$data=array(
|
||||
'v'=>'2.0',
|
||||
'app_key'=>'1',
|
||||
'id'=>$album_id,
|
||||
'r'=>'album/detail',
|
||||
);
|
||||
return $this->curl($url.http_build_query($data));
|
||||
}
|
||||
public function detail($song_id){
|
||||
$url='http://api.xiami.com/web?';
|
||||
$data=array(
|
||||
'v'=>'2.0',
|
||||
'app_key'=>'1',
|
||||
'id'=>$song_id,
|
||||
'r'=>'song/detail',
|
||||
);
|
||||
return $this->curl($url.http_build_query($data));
|
||||
}
|
||||
public function url($song_id){
|
||||
$url='http://www.xiami.com/song/playlist/id/'.$song_id.'/object_name/default/object_id/0/cat/json';
|
||||
return $this->curl($url);
|
||||
}
|
||||
public function playlist($playlist_id){
|
||||
$url='http://api.xiami.com/web?';
|
||||
$data=array(
|
||||
'v'=>'2.0',
|
||||
'app_key'=>'1',
|
||||
'id'=>$playlist_id,
|
||||
'r'=>'collect/detail',
|
||||
);
|
||||
return $this->curl($url.http_build_query($data));
|
||||
}
|
||||
public function lyric($song_id){
|
||||
// Todo
|
||||
return "...";
|
||||
}
|
||||
}
|
||||
36
XiaMiPlayer/ajax.php
Normal file
36
XiaMiPlayer/ajax.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
require dirname(__FILE__) . '/XiamiMusicAPI.php';
|
||||
|
||||
if(!isset($api)){
|
||||
$api = new XiamiMusicAPI();
|
||||
}
|
||||
|
||||
$type = $_GET['type'];
|
||||
$id = $_GET['id'];
|
||||
$page = isset($_GET['page']) ? ($_GET['page'])-1 : 0;
|
||||
|
||||
switch ($type) {
|
||||
case 'songs' :
|
||||
$data=json_decode($api->detail($id));
|
||||
$data = $data ? $data->data->song : null;
|
||||
break;
|
||||
|
||||
case 'album':
|
||||
$data=json_decode($api->album($id));
|
||||
$data = $data ? $data->data : null;
|
||||
break;
|
||||
|
||||
case 'collect':
|
||||
$data=json_decode($api->playlist($id));
|
||||
$data = $data ? $data->data : null;
|
||||
break;
|
||||
|
||||
case 'search':
|
||||
$data=json_decode($api->search($id,5,$page));
|
||||
$data = $data ? $data->data : null;
|
||||
break;
|
||||
}
|
||||
|
||||
header('Content-type: application/json; charset=UTF-8');
|
||||
echo json_encode($data,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
|
||||
exit;
|
||||
BIN
XiaMiPlayer/jplayer/Jplayer.swf
Normal file
BIN
XiaMiPlayer/jplayer/Jplayer.swf
Normal file
Binary file not shown.
1
XiaMiPlayer/jplayer/XiaMiPlayer.css
Normal file
1
XiaMiPlayer/jplayer/XiaMiPlayer.css
Normal file
@@ -0,0 +1 @@
|
||||
.xiamiplayer{cursor:pointer;text-decoration:none;font:12px/1.2 "Helvetica Neue",Helvetica,Arial,sans-serif;overflow:hidden;width:280px;border-radius:3px;}.xiamiplayer,.xiamiplayer .box{background-color:#FF6503;}.xiamiplayer,.xiamiplayer .box{border-bottom:#C4753D 1px solid;}.xiamiplayer .box{display:block;height:30px;white-space:nowrap;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,.2);font-size:14px}.xiamiplayer .box span{float:left;margin-left:10px;line-height:30px;width:240px;overflow:hidden;text-align:left}.xiamiplayer .btn-play{width:0;height:0;border:10px solid transparent;border-left:15px solid #FFF;float:right;margin-top:5px}.xiamiplayer .btn-pause{width:5px;height:20px;border-left:5px solid #FFF;border-right:5px solid #FFF;float:right;margin-top:5px;margin-right:10px}.xiamiplayer .progress{height:30px;background:#C4753D;position:absolute;opacity:0.5;-moz-opacity:0.5;filter:alpha(opacity = 50)}.xiamiplayer .list{padding:0 3px;margin:0;list-style-type:none;}.xiamiplayer .list li{color:#FFF;font-size:14px;line-height:16px;padding:5px 8px;border-bottom:1px solid #FFF;}.xiamiplayer .list li:last-child{border-bottom:none;}.xiamiplayer .display{display:none;}
|
||||
194
XiaMiPlayer/jplayer/index.html
Normal file
194
XiaMiPlayer/jplayer/index.html
Normal file
@@ -0,0 +1,194 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>
|
||||
</title>
|
||||
<meta charset="UTF-8" />
|
||||
<script type="text/javascript" src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js">
|
||||
</script>
|
||||
<script type="text/javascript" src="jquery.jplayer.min.js">
|
||||
</script>
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0
|
||||
}
|
||||
div.openyy {
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
font: 12px/1.2 "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
width: 250px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
white-space: nowrap;
|
||||
background-color: #FF6503;
|
||||
color: #fff;
|
||||
border-bottom: #C4753D 1px solid;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
text-shadow: 0-1px 0 rgba(0, 0, 0, .2);
|
||||
font-size: 14px
|
||||
}
|
||||
.openyy span {
|
||||
float: left;
|
||||
margin-left: 10px;
|
||||
width: 210px;
|
||||
overflow: hidden;
|
||||
text-align: left
|
||||
}
|
||||
#play {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border:10px solid transparent;
|
||||
border-left: 15px solid #FFF;
|
||||
float: right;
|
||||
margin-top: 5px
|
||||
}
|
||||
#pause {
|
||||
width: 5px;
|
||||
height: 20px;
|
||||
border-left: 5px solid #FFF;
|
||||
border-right: 5px solid #FFF;
|
||||
float: right;
|
||||
margin-top: 5px;
|
||||
margin-right: 10px
|
||||
}
|
||||
#progress {
|
||||
height: 30px;
|
||||
background: #FF8F00;
|
||||
position: absolute;
|
||||
opacity: 0.5;-moz-opacity: 0.5;
|
||||
filter: alpha(opacity = 50)
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
var hash = location.hash.split('|');
|
||||
if (hash.length == 3) {
|
||||
var background = '#' + hash[1],
|
||||
border = '#' + hash[2]
|
||||
} else {
|
||||
var background = '#' + hash[2],
|
||||
border = '#' + hash[3]
|
||||
}
|
||||
$('.openyy').css({
|
||||
'background': background,
|
||||
'border-bottom-color': border
|
||||
});
|
||||
|
||||
$('#progress').css({
|
||||
'background': border
|
||||
});
|
||||
var song = hash[0].substr(1);
|
||||
if (song.substring(0, 7) == "http://") {
|
||||
var songs = new Array(hash[0].substr(1), hash[1]),
|
||||
format = songs[0].split('.').pop();
|
||||
$('#jplayer').jPlayer({
|
||||
ready: function() {
|
||||
switch (format) {
|
||||
case 'wma':
|
||||
$(this).jPlayer('setMedia', {
|
||||
wma: songs[0]
|
||||
});
|
||||
break;
|
||||
case 'ogg':
|
||||
$(this).jPlayer('setMedia', {
|
||||
ogg: songs[0]
|
||||
});
|
||||
break;
|
||||
case 'ape':
|
||||
$(this).jPlayer('setMedia', {
|
||||
ape: songs[0]
|
||||
});
|
||||
break;
|
||||
default:
|
||||
$(this).jPlayer('setMedia', {
|
||||
mp3: songs[0]
|
||||
});
|
||||
break
|
||||
}
|
||||
$('title').html(songs[1]);
|
||||
$('.openyy span').html(songs[1])
|
||||
},
|
||||
preload: 'none',
|
||||
ended: function() {
|
||||
$('#pause').click();
|
||||
$('#progress').width('0px')
|
||||
},
|
||||
swfPath: './',
|
||||
supplied: 'mp3,wma,ogg,ape'
|
||||
})
|
||||
} else {
|
||||
$.ajax({
|
||||
url: 'http://imnerd.org/lab/player/apiv2.php?id=' + song,
|
||||
type: 'GET',
|
||||
dataType: 'jsonp',
|
||||
async: false,
|
||||
success: function(d) {
|
||||
$('#jplayer').jPlayer({
|
||||
ready: function() {
|
||||
$(this).jPlayer('setMedia', {
|
||||
mp3: d.location
|
||||
});
|
||||
$('title').html(d.title);
|
||||
$('.openyy span').html(d.title);
|
||||
$.ajax({
|
||||
url: 'http://imnerd.org/lab/search/lyric.php?url=' + d.lyric,
|
||||
type: 'GET',
|
||||
dataType: 'jsonp',
|
||||
async: false,
|
||||
success: function(lrc) {
|
||||
var m = 0;
|
||||
$('#jplayer').bind($.jPlayer.event.timeupdate,
|
||||
function(e) {
|
||||
if (e.jPlayer.status.currentTime > lrc[m][0]) $('.openyy span').html(lrc[m][1]),
|
||||
m++
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
ended: function() {
|
||||
$('#pause').click();
|
||||
$('#progress').width('0px')
|
||||
},
|
||||
preload: 'none',
|
||||
swfPath: './',
|
||||
supplied: 'mp3'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
$('#jplayer').bind($.jPlayer.event.timeupdate,
|
||||
function(e) {
|
||||
$('#progress').width(Math.round(e.jPlayer.status.currentPercentAbsolute / 100 * $('.openyy span').width()))
|
||||
});
|
||||
$('body').on('click', '#play',
|
||||
function() {
|
||||
$('#jplayer').jPlayer('play');
|
||||
$(this).attr('id', 'pause')
|
||||
});
|
||||
$('body').on('click', '#pause',
|
||||
function() {
|
||||
$('#jplayer').jPlayer('pause');
|
||||
$(this).attr('id', 'play')
|
||||
})
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="openyy">
|
||||
<div id="progress">
|
||||
</div>
|
||||
<div id="jplayer">
|
||||
</div>
|
||||
<span>
|
||||
</span>
|
||||
<div id="play"></div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
3101
XiaMiPlayer/jplayer/jquery.jplayer.min.js
vendored
Normal file
3101
XiaMiPlayer/jplayer/jquery.jplayer.min.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
134
XiaMiPlayer/style.css
Normal file
134
XiaMiPlayer/style.css
Normal file
@@ -0,0 +1,134 @@
|
||||
.wmd-button#wmd-music-button {
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
color: #AAA;
|
||||
width: 20px;
|
||||
float: left;
|
||||
}
|
||||
.wmd-prompt-background {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
z-index: 1000;
|
||||
opacity: 0.5;
|
||||
left: 0px
|
||||
}
|
||||
input#xiami_search {
|
||||
width: 270px;
|
||||
height: 28px;
|
||||
float: left
|
||||
}
|
||||
#searchPanel .wmd-prompt-dialog{
|
||||
position:absolute;
|
||||
}
|
||||
#searchPanel form {
|
||||
padding: 6px
|
||||
}
|
||||
#DoSearch {
|
||||
-moz-box-shadow: inset 0px 1px 0px 0px #ffffff;
|
||||
-webkit-box-shadow: inset 0px 1px 0px 0px #ffffff;
|
||||
box-shadow: inset 0px 1px 0px 0px #ffffff;
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ededed), color-stop(1, #dfdfdf));
|
||||
background: -moz-linear-gradient(center top, #ededed 5 % , #dfdfdf 100 % );
|
||||
filter: progid: DXImageTransform.Microsoft.gradient(startColorstr = '#ededed', endColorstr = '#dfdfdf');
|
||||
background-color: #ededed;
|
||||
-moz-border-radius: 6px;
|
||||
-webkit-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid#dcdcdc;
|
||||
display: inline-block;
|
||||
color: #777777;
|
||||
font-family: arial;
|
||||
font-size: 15px;
|
||||
font-weight: normal;
|
||||
padding: 10px 15px;
|
||||
margin-left: 10px;
|
||||
text-decoration: none;
|
||||
text-shadow: 1px 1px 0px#ffffff
|
||||
}
|
||||
#DoSearch:hover {
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0.05, #dfdfdf), color-stop(1, #ededed));
|
||||
background: -moz-linear-gradient(center top, #dfdfdf 5 % , #ededed 100 % );
|
||||
filter: progid: DXImageTransform.Microsoft.gradient(startColorstr = '#dfdfdf', endColorstr = '#ededed');
|
||||
background-color: #dfdfdf;
|
||||
cursor: pointer
|
||||
}
|
||||
#DoSearch:active {
|
||||
position: relative;
|
||||
top: 1px
|
||||
}
|
||||
#searchPanel .close {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
padding: 6px;
|
||||
-moz-border-radius: 3px;
|
||||
-khtml-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
color: #000;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
text-align: center;
|
||||
line-height: 10px;
|
||||
font-size: 20px
|
||||
}
|
||||
#searchPanel #xiami_list a {
|
||||
display: block;
|
||||
padding: 6px;
|
||||
border-bottom: 1px solid#ddd
|
||||
}
|
||||
ul#tab {
|
||||
margin: 0px;
|
||||
padding: 0px
|
||||
}
|
||||
#tab li: hover {
|
||||
cursor: pointer;
|
||||
background: #467b96;
|
||||
color: #FFF
|
||||
}
|
||||
#tab .multi {
|
||||
color:#DDD;
|
||||
}
|
||||
#tab .multi.checked {
|
||||
color:#000;
|
||||
font-weight:bold;
|
||||
}
|
||||
.select {
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
#playlist {
|
||||
padding-left:25px;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
#playlist li {
|
||||
cursor:move;
|
||||
box-sizing:border-box;
|
||||
line-height:20px;
|
||||
list-style-type:square;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
#playlist .sortable {
|
||||
border:1px dashed #AAA;
|
||||
background:#DDD;
|
||||
}
|
||||
li.hover {
|
||||
position:absolute;
|
||||
list-style-type:none;
|
||||
}
|
||||
Reference in New Issue
Block a user