您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
open xiami.com and iirose.com at the same time. Play any song with xiami and it will pushed automatically to iirose.com. Just mute one of them. 使用方法:同时打开虾米Xiami.com和iirose.com,使用虾米收听的任何歌曲都会同步推送至iirose。
当前为
// ==UserScript== // @name Picking Songs With Xiami in iirose.com // @namespace http://tampermonkey.net/ // @version 2.0 // @description open xiami.com and iirose.com at the same time. Play any song with xiami and it will pushed automatically to iirose.com. Just mute one of them. 使用方法:同时打开虾米Xiami.com和iirose.com,使用虾米收听的任何歌曲都会同步推送至iirose。 // @author KeaneW // @match https://iirose.com/messages.html // @match https://emumo.xiami.com/radio/play/* // @match https://www.xiami.com/* // @grant GM.setValue // @grant GM.getValue // ==/UserScript== (function() { 'use strict'; //get url of current page var url = window.location.href; GM.setValue("song", -5);//default to be -5 means null var autoPicking = true; //save a shuffled song list and current pointer var shuffledSongList = []; var shufflePointer = 0; //for xiami radio page if (url.search("xiami.com/radio")>=0){ var timerXiami = setInterval(function(){ if(document.getElementsByClassName("artist_info fl")[0]!=undefined){ clearInterval(timerXiami); xiami_old(); } }, 1000); } //for iirose else if (url.search("iirose.com")>=0){ iirose(); } else if (url.search("xiami.com")>=0){ xiami_new(); } else { console.log("Failed to match the website!"); } //a quick shuffle algorithm function shuffleArray(array) { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } } //simple sleep function function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } //xiami Collection starts function xiamiCollection(){ //generate a button console.log("51"); var parentDiv = document.getElementById("element_r"); var newNode = document.createElement ('div'); newNode.innerHTML='<form style="font-size:16px">' +'<br><br>给蔷薇花园点歌!<br><br>' +'从:<input type="number" name="startNum" max="50" style="border: 2px solid red;font-size: 16px;"> <br><br>到:<input type="number" name="endNum" style="border: 2px solid red;font-size: 16px;"><br><br>' +'点:<input type="number" name="pickNum" min="1" max="10" style="border: 2px solid red;font-size: 16px;"> 首<br><br>' +'<input type="checkbox" name="random" value="random" style="border: 2px solid red;font-size: 16px;"> 随机播放<br><br>' +'<input id="pick!" type="button" style="background-color: #4CAF50;font-size: 16px;text-align:center;" value=" 点歌! "> <br><br>' +'<input id="pickFive!" type="button" style="background-color: #4CAF50;font-size: 16px;text-align:center;" value=" 点五首歌! "> </form>'; parentDiv.appendChild (newNode); document.getElementById("pick!").addEventListener("click", pickCollection); document.getElementById("pickFive!").addEventListener("click", pickCollectionFive); /* <form> 从: <input type="number" name="startNum" min="1" max="5"> 到: <input type="number" name="endNum" min="1" max="5"> <br> 点 <input type="number" name="pickNum" min="1" max="5"> 首 <br> <input type="checkbox" name="random" value="random"> 随机播放<br> <input type="submit"> </form> */ } // async function pickCollection(){ //for xiami collection console.log("84"); var songList = getSongList(); console.log("song size is "+songList.length); var pickList = []; var startP = document.getElementsByName("startNum")[0].value; var endP = document.getElementsByName("endNum")[0].value; var range = document.getElementsByName("pickNum")[0].value; var random = document.getElementsByName("random")[0].checked; console.log("new89"+startP+endP+range+random); if (isNaN(startP)){ startP=0; } if (isNaN(endP)){ endP=50; } if (isNaN(range)){ range=5; } startP = parseInt(startP);endP = parseInt(endP);range = parseInt(range); if (range>endP-startP){startP=1;endP=50; } pickList = songList.slice(startP, endP); if (random){ shuffleArray(pickList); } var song; var count = 1; await sleep(2000); for (song of pickList){ if (count>range){break;} song.replace( /\s\s+/g, ' ' ); GM.setValue("song", song); console.log("sended "+song); count += 1; await sleep(2000); } } async function pickCollectionFive(){ //for xiami collection if (shuffledSongList.length==0){ shuffledSongList = getSongList(); shuffleArray(shuffledSongList); } console.log("song size is "+shuffledSongList.length); var pickList = []; var range = 5; console.log("ShufflePointer (before):"+shufflePointer); if (shufflePointer+range+1>shuffledSongList.length){ pickList=shuffledSongList.slice(shufflePointer).concat(shuffledSongList.slice(0, shufflePointer+range-shuffledSongList.length)); shufflePointer=shufflePointer+range-shuffledSongList.length; } else { pickList = shuffledSongList.slice(shufflePointer, shufflePointer+range); shufflePointer=shufflePointer+range; } console.log("ShufflePointer (after):"+shufflePointer); var song; var count = 1; await sleep(2000); for (song of pickList){ song.replace( /\s\s+/g, ' ' ); GM.setValue("song", song); console.log("sended "+song); await sleep(2000); } } function getSongList(){ var list = document.getElementsByClassName("song_name"); var listSize = list.length; var tempNode; var songList = []; for (tempNode of list){ var songNameList=tempNode.innerText.split("-—")[0].split(" "); // like ["Return", "Of", "The", "Mack", "(...", ""] var tempSoneNameNode; var songName=""; for (tempSoneNameNode of songNameList){ if (tempSoneNameNode.search(/\.\.\./)>=0){ //console.log("99"+tempSoneNameNode); break; } tempSoneNameNode=tempSoneNameNode.replace('(','').replace(')',''); songName += tempSoneNameNode; songName += ' '; } var artisitList=tempNode.innerText.split("-—")[1].split(";");//like [" Dale Castell", "Tamia"] var lastWord = artisitList[artisitList.length-1].split(' ').slice(-1)[0]; if (lastWord=='MV'){ //console.log('before: '+artisitList); artisitList[artisitList.length-1]=artisitList[artisitList.length-1].split(' ').slice(0,-1).join(' '); //console.log('after: '+artisitList); } var artisitName=artisitList.join(' '); songList.push(songName+'|'+artisitName); //console.log(songName+'|'+artisitName); } return songList; } //play with xiami function xiami_old(){ //send first message to iirose xiamiInfoParser(false); //an api that can be used to monitor changes in the webpage var mutationObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { //console.log(mutation); //send message whenever it observers a change xiamiInfoParser(false); }); }); //it focuses on the title of the page mutationObserver.observe(document.querySelector('title'), { attributes: true, characterData: true, childList: true, subtree: true, attributeOldValue: true, characterDataOldValue: true }); } function xiami_new(){ sleep(200); //send first message to iirose, or not //xiamiSendMessage(xiamiInfoParser(false)); addXMLRequestCallback( function( xhr ) { //check if is getPlayInfo request if (xhr.__sufei_url.search("getPlayInfo")>-1){ var songID = xhr.__sufei_url.split('[')[1].split(']')[0]; console.log("the new song's ID is "+songID.toString()); xiamiInfoParser(true, songID); } }); } function addXMLRequestCallback(callback){ var oldSend, i; if( XMLHttpRequest.callbacks ) { // we've already overridden send() so just add the callback XMLHttpRequest.callbacks.push( callback ); } else { // create a callback queue XMLHttpRequest.callbacks = [callback]; // store the native send() oldSend = XMLHttpRequest.prototype.send; // override the native send() XMLHttpRequest.prototype.send = function(){ // process the callback queue // the xhr instance is passed into each callback but seems pretty useless // you can't tell what its destination is or call abort() without an error // so only really good for logging that a request has happened // I could be wrong, I hope so... // EDIT: I suppose you could override the onreadystatechange handler though for( i = 0; i < XMLHttpRequest.callbacks.length; i++ ) { XMLHttpRequest.callbacks[i]( this ); } // call the native send() oldSend.apply(this, arguments); } } } function xiamiInfoParser(isnew, songID=""){ if(isnew){ console.log("sending " + songID.toString()); xiamiSendMessage(songID); } else{ var timerXiamiMessage = setInterval(function () { //this timer waits for the page to load every 0.1s //if the artist info is loaded we assume the page finished loading cuz that's what we need. if(document.getElementsByClassName("artist_info fl")[0]!=null){ clearInterval(timerXiamiMessage); //get song name and artist name var songName = document.title.split("——")[0]; var artistName = document.getElementsByClassName("artist_info fl")[0].getElementsByTagName("strong")[0].innerHTML; var message = songName+"|"+artistName; xiamiSendMessage( message); //set the "song" value with the above info } }, 100);} } //collect and send info to iirose function xiamiSendMessage(msg){ GM.setValue("song", msg); console.log("sended "+msg); } //play with iirose async function iirose(){ //this timer checks if the window has loaded. Do checking every 3 seconds. if (autoPicking){ var timer = setInterval(function () { if(document.getElementById("moveinput")!=null){ clearInterval(timer); //current song info var tempSong=-5; //this timer checks if there is a new message from xiami var pickTimer = setInterval(async function () { //get value from xiami. If not changed, do nothing and wait var realSong = await GM.getValue("song", -5); if(realSong!=tempSong){ //changed! pick the real song here console.log("successfully recieve message "+realSong); await pickingSong(realSong); //update tempSong tempSong = realSong; } //console.log("one more loop in iirose"); }, 500); } }, 3000); } //add entryIirose() to console /*var scriptText='function entryIirose(str){ if(str.length>14){console.log("智障吗,搞那么长?");str="艰苦奋斗严肃活泼";} var rainbow=["C30002", "C30040", "C3007D", "C300BB", "8D00C3", "4F00C3", "1200C3", "002AC3", "0068C3", "00A5C3", "00C3A2", "00C365", "00C327", "15C300", "52C300", "90C300", "C3B800", "C37A00", "C33D00", "C30000", "C30022", "C30060", "C3009D", "AA00C3", "6D00C3", "2F00C3", "000DC3", "004AC3", "0088C3", "00C3C0", "00C382", "00C345", "00C307", "35C300", "72C300", "B0C300", "C39800", "C35A00", "C31D00", "C3001F"];var offset=Math.floor(Math.random()*rainbow.length);var text=str.split("");for(var i=0;i<text.length;i++){if(offset+i<rainbow.length){console.log(\'%c \'+rainbow[offset+i],\'color: #\'+rainbow[offset+i]);socket.send(\'{"m": "\'+text[i]+\'", "mc": "\'+rainbow[offset+i]+\'"}\')} else{socket.send(\'{"m": "\'+text[i]+\'", "mc": "\'+rainbow[offset+i-rainbow.length]+\'"}\');console.log(\'%c \'+rainbow[offset+i], \'color: #\'+rainbow[offset+i]);}}}'; addScript(scriptText); //whether show rainbow effect if(entryEffect){ entryIirose(null); } if (autoSpamming){ setInterval(function(){ entryIirose("自动刷屏123456789"); },300000); } */ return; } //pick a song with the sring function DirectPicking(url) { var t = url.trim(); if (t) { var o = t.match(Variable.regexp.assets.getLink); o ? ("[" == t[0] && (o[0] = t.replace(Variable.regexp.pregmedia.linkSpaceAround2, "$1")), Utils.service.moveinputDo("<> " + o[0])) : "#" == t[0] ? Utils.service.moveinputDo(t) : (-1 < Constant.Shortcuts.all.indexOf("@" + t) && (t += " "), Utils.service.moveinputDo("@" + (" " == e[0] ? " " : "") + t)) } } function pickingSong(songInfo){ if (songInfo=='-5') return; if(!isNaN(songInfo)){ console.log('recieved songID '+songInfo); var url = "https://www.xiami.com/song/"+songInfo.toString(); DirectPicking(url); } else{ var str = songInfo.replace("|"," "); inputString("@"+str); //this timer checks whether the search results have loaded var timer2 = setInterval(function () { //if find nothing OR have found some songs, end the timer if((document.getElementsByClassName("emptyShow")[0]!=null)||(document.getElementsByClassName("demandHolderPlayBtn")[0]!=null)){ //if find something if(document.getElementsByClassName("emptyShow")[0]==null){ var songList = document.getElementsByClassName("demandHolderPlayBtn"); //console.log(songList[0]); if(songList[0].getElementsByClassName("mainColor")[0].getElementsByClassName("buttonText")[0]!=null){ clearInterval(timer2); //if successfully pick a song var flag = 0; //loop until one button can be clicked for (var i = 0; i < songList.length; i++) { var node = null; for (var j = 0; j < songList[i].childNodes.length; j++) { if (songList[i].childNodes[j].className == "mainColor") { node = songList[i].childNodes[j]; break; } } //check if clickable if (node.hasAttribute("onclick")){ node.click(); console.log("pick "+i); flag=1; break; } console.log("cannot pick "+i); } //no button was clicked. Go back if (flag==0){ //click return console.log("failed"); //document.getElementsByClassName("footerItemBgShape_pointer")[0].onclick.apply(); Objs.demandHolder.function.event.call(this,0); inputString("点歌失败,因为没有 "+str+" 的版权。"); } } } //if find nothing else { //这里有bug!! clearInterval(timer2); Objs.demandHolder.function.event.call(this,0); //document.getElementsByClassName("footerItemBgShape_pointer")[0].onclick.apply(); var strList=songInfo.split("|"); if (strList.length>1){ inputString("点歌失败,因为搜索不到 "+str+"。尝试模糊搜索 "+strList[0]); setTimeout(function(){pickingSong(strList[0]);}, 1000) } else{ inputString("模糊搜索也失败了。"); //location.reload(); } } } // }, 800); //var newSize = songlist.length;//for future use } } //some tools //this method types and submit a string in the typearea function inputString(str){ /* var inputBox = document.getElementById("moveinput"); var originText = inputBox.value; var submit = document.getElementsByClassName("moveinputSendBtn")[0]; inputBox.value = str; submit.click(); inputBox.value = originText; */ Utils.service.moveinputDo(str); } //this method add a script to html so that u can use the script in console function addScript(scriptText){ var scriptElem = document.createElement('script'); scriptElem.innerHTML = scriptText; document.body.appendChild(scriptElem); } //show a rainbow when enter a room. Very annoying! //expired /* async function entryIirose(str){ if(str !=null){GM.setValue("entry",str);} str = await GM.getValue("entry", "我踩着七彩祥云来了~") if(str.length>13){ console.log("智障吗,搞那么长?"); str="本人专属跑马灯入场"; GM.setValue("entry",str); } var rainbow = ["C30002", "C30040", "C3007D", "C300BB", "8D00C3", "4F00C3", "1200C3", "002AC3", "0068C3", "00A5C3", "00C3A2", "00C365", "00C327", "15C300", "52C300", "90C300", "C3B800", "C37A00", "C33D00", "C30000", "C30022", "C30060", "C3009D", "AA00C3", "6D00C3", "2F00C3", "000DC3", "004AC3", "0088C3", "00C3C0", "00C382", "00C345", "00C307", "35C300", "72C300", "B0C300", "C39800", "C35A00", "C31D00", "C3001F"]; // var rainbow = ["00ABE5", "0063E5", "001CE6", "2C00E7", "7400E8", "BE00E9", "EA00CC", "EA0083", "EB003A", "EC0F00", "ED5900", "EEA400", "EEEF00", "A4EF00", "5AF000", "0EF100", "00F23C", "00F389", "00F4D5", "00C7F5","007DF5", "0033F5", "1600F5", "6000F5", "AA00F5", "F400F5", "F500AB", "F50060", "F50016", "F53300", "F57D00", "F5C700", "D8F500", "8DF500", "43F500", "00F506", "00F550", "00F59A", "00F5E4", "00BBF5"]; var offset = Math.floor(Math.random() * rainbow.length); var text = str.split(""); for (var i=0;i<text.length;i++){ if(offset+i<rainbow.length){ console.log('%c '+rainbow[offset+i], 'color: #'+rainbow[offset+i]); socket.send('{"m": "'+text[i]+'", "mc": "'+rainbow[offset+i]+'"}'); } else { console.log('%c '+rainbow[offset+i], 'color: #'+rainbow[offset+i]); socket.send('{"m": "'+text[i]+'", "mc": "'+rainbow[offset+i-rainbow.length]+'"}'); } } } */ // Your code here... })();