Last active
January 28, 2017 18:55
-
-
Save siliconbrain/3e186a74a62e94196a158d1452b9e6d9 to your computer and use it in GitHub Desktop.
Tampermokey script for displaying music policy information for music videos on YouTube
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name YouTube music policy display | |
// @namespace http://tampermonkey.net/ | |
// @version 0.1 | |
// @description Show music policy info for music videos | |
// @author siliconbrain | |
// @match https://www.youtube.com/* | |
// @grant none | |
// ==/UserScript== | |
function ajax(url, success, error) { | |
var xhr = new XMLHttpRequest(); | |
xhr.onreadystatechange = function() { | |
if (this.readyState == 4) { | |
if (this.status >= 200 && this.status < 300) { | |
if (success) success(this.responseText); | |
} else { | |
if (error) error(this.status, this.responseText); | |
} | |
} | |
}; | |
xhr.open('GET', url, true); | |
xhr.send(); | |
return xhr; | |
} | |
function getMusicPolicyInfoElement() { | |
var id = 'musicPolicyInfo'; | |
var musicPolicyInfoElement = document.querySelector('#' + id); | |
if (!musicPolicyInfoElement) { | |
musicPolicyInfoElement = document.createElement('div'); | |
musicPolicyInfoElement.id = 'musicPolicyInfo'; | |
musicPolicyInfoElement.innerHTML = 'Determining availability...'; | |
document.querySelector('#watch-headline-title').append(musicPolicyInfoElement); | |
} | |
return musicPolicyInfoElement; | |
} | |
function videoTitleToQuery(title) { | |
return title | |
.replace(/\bft\b/gi, 'feat') | |
.replace(/[\[\(](audio|lyric|music|official|video|\s)+[\]\)]/gi, '') | |
.replace(/[^\w\d\u00C0-\u017F]/g, ' '); | |
} | |
function getWords(str) { | |
return str | |
.replace(/[^\w\d\u00C0-\u017F]/g, ' ') | |
.trim() | |
.replace(/ (?= )/g, '') | |
.split(' '); | |
} | |
function symmetricDifference(setA, setB) { | |
var all = setA.concat(setB); | |
return all.reduce((set, val) => (setA.indexOf(val) >= 0 && setB.indexOf(val) >= 0) ? set : set.concat([val]), []); | |
} | |
function bestMatch(query, tracks) { | |
if (tracks.length == 1) return tracks[0]; | |
var queryWords = getWords(query).map(w => w.toLowerCase()); | |
var tracksWords = tracks.map(track => getWords(track.artist).concat(getWords(track.title)).map(w => w.toLowerCase())); | |
var diffs = tracksWords.map(trackWords => symmetricDifference(queryWords, trackWords)); | |
var ranks = diffs.map(d => d.length); | |
var best = ranks.reduce((cur, val, idx) => val < cur.val ? {idx: idx, val: val} : cur, {idx: 0, val: Infinity}); | |
console.log('bestMatch', queryWords, tracksWords, diffs, best); | |
return tracks[best.idx]; | |
} | |
function loadMusicPolicy(player) { | |
if (player.getCurrentVideoConfig().args.vmap.match(/ytpwatch.music/) || document.querySelector('meta[itemprop="genre"][content="Music"]')) { | |
var q = videoTitleToQuery(player.getVideoData().title); | |
console.info('Music policy query string:', q); | |
ajax(`https://www.youtube.com/audioswap_ajax?action_get_tracks=1&s=ad_supported_music&q=${encodeURI(q)}`, function(resp) { | |
var musicPolicyInfoElement = getMusicPolicyInfoElement(); | |
resp = JSON.parse(resp); | |
var tracks = resp.tracks; | |
console.info('Music policy query results:', tracks); | |
if (tracks.length > 0) { | |
var track = bestMatch(q, tracks); | |
var trackName = `${track.title} by ${track.artist}`; | |
ajax(`https://www.youtube.com/audioswap_ajax?action_get_track_details=1&asset_id=${track.asset_id}&isrc=${track.isrc}`, function(resp) { | |
resp = JSON.parse(resp); | |
if (resp.is_available) { | |
if (resp.sr_policy.restrictions) { | |
musicPolicyInfoElement.innerHTML = `© ${trackName} is blocked in ${resp.sr_policy.restrictions.blocked_terr_names.length} countries.`; | |
} else { | |
musicPolicyInfoElement.innerHTML = `✓ ${trackName} is viewable worldwide.`; | |
} | |
} else { | |
musicPolicyInfoElement.innerHTML = `✗ ${trackName} is not available for playback.`; | |
} | |
if (tracks.length > 1) musicPolicyInfoElement.innerHTML += ` (best of ${tracks.length} results)`; | |
}); | |
} else { | |
musicPolicyInfoElement.innerHTML = `⚠ Track info not found.`; | |
} | |
}); | |
} | |
} | |
function addPlayerEventListener(player, event, name, handler) { | |
window[name] = handler; | |
player.addEventListener(event, name); | |
} | |
(function() { | |
'use strict'; | |
var player = yt.player.getPlayerByElement('player-api'); | |
addPlayerEventListener(player, 'onReady', 'playerReadyHandlerForMusicPolicy', function() { | |
var lastVideoId = player.getVideoData().video_id; | |
addPlayerEventListener(player, 'onStateChange', 'playerStateChangeHandlerForMusicPolicy', function(state) { | |
var videoId = player.getVideoData().video_id; | |
if (state == 1 && lastVideoId != videoId) { | |
lastVideoId = videoId; | |
loadMusicPolicy(player); | |
} | |
}); | |
if (lastVideoId) loadMusicPolicy(player); | |
}); | |
//window.THE_PLAYER = player; // for debugging | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment