// ==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 // @downloadURL none // ==/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='
'; parentDiv.appendChild (newNode); document.getElementById("pick!").addEventListener("click", pickCollection); document.getElementById("pickFive!").addEventListener("click", pickCollectionFive); /* */ } // 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