您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Spotify - Append Artist Name and Title to Copied Link.
// ==UserScript== // @name Spotify - Append Artist Name and Title to Copied Link // @description Spotify - Append Artist Name and Title to Copied Link. // @author to // @namespace https://github.com/to // @license MIT // @version 0.6 // // @noframes // @connect spotify.com // @connect song.link // @match https://open.spotify.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=spotify.com // // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant unsafeWindow // ==/UserScript== // SpotifyのAPIを利用すると 日本のアーティストが日本語表記になりやすい const CLIENT_ID = ''; const CLIENT_SECRET = ''; const MARKETS = ['JP', 'US']; const PREFIX = ""; let useSpotify = !!CLIENT_ID; let market = MARKETS[0]; // Clipboard APIではcopyイベントが発生しないため 強制的にexecCommandを利用させる unsafeWindow.navigator.clipboard.write = null; unsafeWindow.navigator.clipboard.writeText = null; // マーケットの国を切り替える // (海外のアーティストがカタカナ表記になってしまうことがあるため) MARKETS.forEach(m => { GM_registerMenuCommand ('Change Market [' + m + ']', () => { market = m; }); }); if(useSpotify){ GM_registerMenuCommand ('Use Odesil', () => { useSpotify = false; }); } document.addEventListener('copy', e => { // URL以外がコピーされたか、または、通常のテキストコピー操作か? let url = e.target.value; if(!url || !(/^http/.test(url) || !(e.target instanceof HTMLTextAreaElement))) return; url = url.replace(/\?.+/, ''); // SpotifyのAPIを利用するか? if(useSpotify){ let ts = url.match(/\/(track|album)\/(.+)/); if(ts){ requestToSpotify(`https://api.spotify.com/v1/${ts[1]}s/${ts[2]}?market=${market}`, r => { GM_setClipboard([ r.artists.map(a => a.name).join(', '), '-', r.name, url, 'https://' + (r.type == 'track' ? 'song' : r.type) + '.link/s/' + r.id].join(' ') + PREFIX); }); } } else { // JPロケールが適用されていない(USと同じ値が返される) GM_xmlhttpRequest({ url: `https://api.song.link/v1-alpha.1/links?userCountry=${market}&url=${encodeURIComponent(url)}`, onload: function(r){ r = JSON.parse(r.responseText); GM_setClipboard([ r.entitiesByUniqueId[r.entityUniqueId].artistName, '-', r.entitiesByUniqueId[r.entityUniqueId].title, url, r.pageUrl].join(' ') + PREFIX); }}); } }, true); function requestToSpotify(url, callback){ GM_xmlhttpRequest({ url: 'https://accounts.spotify.com/api/token', method: 'POST', data: 'grant_type=client_credentials', headers: { 'Authorization': 'Basic ' + btoa(CLIENT_ID + ':' + CLIENT_SECRET), 'Content-Type': 'application/x-www-form-urlencoded', }, onload: function(r){ r = JSON.parse(r.responseText); GM_xmlhttpRequest({ url: url, headers: { 'Authorization': r.token_type + ' ' + r.access_token, 'Content-Type': 'application/json', }, onload: function(r){ callback(JSON.parse(r.responseText)); }}); }}); }