您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Click a floating button to get the last played song from Last.fm and search it on Netease Music
// ==UserScript== // @name SP2netease Custom // @namespace http://tampermonkey.net/ // @version 1.1 // @description Click a floating button to get the last played song from Last.fm and search it on Netease Music // @author You // @match *://*/* // @grant GM_addStyle // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @connect last.fm // ==/UserScript== (function() { 'use strict'; // 存储工具函数 const storage = { // 设置存储 setItem: function(key, value) { try { // 首先尝试使用油猴存储API(跨域) if (typeof GM_setValue !== 'undefined') { GM_setValue(key, value); console.log('使用GM_setValue保存:', key, value); return; } } catch (e) { console.log('GM_setValue不可用:', e); } try { // 然后尝试使用localStorage localStorage.setItem(key, value); console.log('使用localStorage保存:', key, value); } catch (e) { // localStorage不可用时使用cookie console.log('localStorage不可用,使用cookie保存:', key, value); this.setCookie(key, value, 365); } }, // 获取存储 getItem: function(key) { try { // 首先尝试使用油猴存储API(跨域) if (typeof GM_getValue !== 'undefined') { const value = GM_getValue(key, null); console.log('从GM_getValue读取:', key, value); return value; } } catch (e) { console.log('GM_getValue不可用:', e); } try { // 然后尝试使用localStorage const value = localStorage.getItem(key); console.log('从localStorage读取:', key, value); return value; } catch (e) { // localStorage不可用时使用cookie console.log('localStorage不可用,从cookie读取:', key); return this.getCookie(key); } }, // 设置cookie setCookie: function(name, value, days) { let expires = ""; if (days) { const date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); expires = "; expires=" + date.toUTCString(); } // 设置cookie为跨域共享 document.cookie = name + "=" + (value || "") + expires + "; path=/; domain=." + window.location.hostname.split('.').slice(-2).join('.'); }, // 获取cookie getCookie: function(name) { const nameEQ = name + "="; const ca = document.cookie.split(';'); for (let i = 0; i < ca.length; i++) { let c = ca[i]; while (c.charAt(0) === ' ') c = c.substring(1, c.length); if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); } return null; } }; // 创建设置面板 const createSettingsPanel = () => { // 创建面板元素 const panel = document.createElement('div'); panel.id = 'netease-settings-panel'; // 添加面板内容 panel.innerHTML = ` <div class="netease-settings-header"> <h3>Last.fm 用户名设置</h3> <button id="close-settings">×</button> </div> <div class="netease-settings-content"> <label for="lastfm-username">用户名:</label> <input type="text" id="lastfm-username" placeholder="请输入Last.fm用户名"> <button id="save-settings">保存</button> </div> `; // 设置输入框的默认值 const usernameInput = panel.querySelector('#lastfm-username'); const savedUsername = storage.getItem('lastfmUsername'); // 调试信息 console.log('从存储中读取到的用户名:', savedUsername); if (savedUsername !== null && savedUsername !== '') { usernameInput.value = savedUsername; console.log('设置输入框默认值为:', savedUsername); } else { console.log('未设置输入框默认值'); } // 设置面板为浮动窗口样式 panel.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 300px; background: white; border: 1px solid #ccc; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.3); z-index: 10002; padding: 20px; `; // 设置面板头部样式 const header = panel.querySelector('.netease-settings-header'); header.style.cssText = ` display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; `; // 设置关闭按钮样式 const closeButton = panel.querySelector('#close-settings'); closeButton.style.cssText = ` background: none; border: none; font-size: 20px; cursor: pointer; padding: 0; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; `; // 设置内容区域样式 const content = panel.querySelector('.netease-settings-content'); content.style.cssText = ` display: flex; flex-direction: column; gap: 10px; `; // 设置标签样式 const label = panel.querySelector('label'); label.style.cssText = ` font-weight: bold; `; // 设置输入框样式 const input = panel.querySelector('input'); input.style.cssText = ` padding: 8px; border: 1px solid #ccc; border-radius: 4px; `; // 设置保存按钮样式 const saveButton = panel.querySelector('#save-settings'); saveButton.style.cssText = ` padding: 10px; background-color: #E20000; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; `; // 将面板添加到页面 document.body.appendChild(panel); // 添加事件监听器 document.getElementById('close-settings').addEventListener('click', () => { panel.remove(); }); document.getElementById('save-settings').addEventListener('click', () => { const username = document.getElementById('lastfm-username').value.trim(); if (username) { try { storage.setItem('lastfmUsername', username); alert('设置已保存'); panel.remove(); } catch (e) { alert('保存失败: ' + e.message); // 保存失败时不移除面板,让用户重新尝试 } } else { alert('请输入有效的用户名'); // 不移除面板,让用户重新输入 } }); // 点击面板外部关闭面板 panel.addEventListener('click', (e) => { if (e.target === panel) { panel.remove(); } }); // 阻止事件冒泡到面板外部 const contentElement = panel.querySelector('.netease-settings-content'); contentElement.addEventListener('click', (e) => { e.stopPropagation(); }); }; // 创建浮动按钮 const createFloatingButton = () => { // 创建按钮元素 const button = document.createElement('div'); button.id = 'netease-search-button'; // 添加SVG图标 button.innerHTML = '<svg t="1754156884017" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3730" width="32" height="32"><path d="M512 32c265.12 0 480 214.88 480 480 0 265.088-214.88 480-480 480-265.088 0-480-214.912-480-480C32 246.848 246.912 32 512 32z m82.08 173.568c-51.84 17.152-76.736 65.44-61.856 120.32l5.344 20.192c-11.2 2.432-22.208 5.696-32.928 9.824-50.656 19.52-90.848 62.816-104.896 113.024a153.696 153.696 0 0 0-5.088 55.04 137.92 137.92 0 0 0 57.536 100.576 121.504 121.504 0 0 0 103.264 17.6 120.96 120.96 0 0 0 63.68-42.56c24.736-32.288 32.096-74.752 20.8-119.52-4.16-16.32-9.344-34.368-14.4-51.904l-5.376-18.976c21.44 5.376 41.184 16.032 57.44 31.04 56 52.288 66.784 142.368 25.088 209.536-36.608 59.008-107.936 97.088-181.664 97.088a225.76 225.76 0 0 1-225.536-225.472c0-28.992 5.696-57.696 16.832-84.448a221.664 221.664 0 0 1 41.856-65.6 223.712 223.712 0 0 1 81.408-56.416A31.712 31.712 0 0 0 412.064 256a299.52 299.52 0 0 0-25.696 11.808 289.504 289.504 0 0 0-100 86.432 286.56 286.56 0 0 0-54.304 167.136c0 159.296 129.6 288.896 288.96 288.896 95.2 0 187.648-49.856 235.552-127.072 58.304-93.888 43.232-215.584-35.712-289.344-32.32-30.208-74.368-47.872-118.784-51.776-2.304-8.96-5.888-22.592-8.64-32.832-2.08-7.584-3.104-16.16-0.864-23.808a31.808 31.808 0 0 1 38.4-21.44c4.416 1.184 8.608 3.264 12.256 6.048 3.84 2.88 6.848 6.624 10.368 9.888a31.744 31.744 0 0 0 49.856-37.664l-0.64-1.056a65.312 65.312 0 0 0-14.4-16.448 100.48 100.48 0 0 0-53.376-23.392 96.128 96.128 0 0 0-40.96 4.224z m-40.224 201.92c3.36 12.416 7.04 25.344 10.752 38.176 4.928 17.28 9.888 34.432 13.824 49.92 4.576 18.176 6.624 44.192-9.664 65.472a57.056 57.056 0 0 1-30.24 19.936 58.464 58.464 0 0 1-50.144-8.544 73.92 73.92 0 0 1-30.528-53.952 89.6 89.6 0 0 1 2.944-32.416c8.8-31.36 34.304-58.528 66.624-71.008 8.672-3.36 17.536-5.856 26.432-7.584z" fill="#FFFFFF" p-id="3731"></path></svg>'; // 添加按钮样式 GM_addStyle(` #netease-search-button { position: fixed; width: 32px; height: 32px; border-radius: 50%; background-color: #E20000; /* 红色背景 */ cursor: pointer; z-index: 10000; box-shadow: 0 2px 10px rgba(0,0,0,0.3); transition: opacity 0.3s; display: flex; justify-content: center; align-items: center; } #netease-search-button:hover { opacity: 0.8; } #netease-search-button svg { width: 100%; height: 100%; } `); // 设置按钮初始位置 // 从存储中读取保存的位置,如果没有则使用默认位置 const savedPosition = storage.getItem('neteaseButtonPosition'); if (savedPosition) { const position = JSON.parse(savedPosition); button.style.left = position.x + 'px'; button.style.top = position.y + 'px'; } else { button.style.left = '20px'; button.style.top = '20px'; } // 添加拖动功能 let isDragging = false; let offsetX, offsetY; button.addEventListener('mousedown', (e) => { isDragging = true; offsetX = e.clientX - button.getBoundingClientRect().left; offsetY = e.clientY - button.getBoundingClientRect().top; button.style.cursor = 'grabbing'; e.preventDefault(); }); document.addEventListener('mousemove', (e) => { if (!isDragging) return; button.style.left = (e.clientX - offsetX) + 'px'; button.style.top = (e.clientY - offsetY) + 'px'; }); document.addEventListener('mouseup', () => { isDragging = false; button.style.cursor = 'pointer'; // 保存按钮位置到存储 const position = { x: button.offsetLeft, y: button.offsetTop }; storage.setItem('neteaseButtonPosition', JSON.stringify(position)); }); // 添加右键点击功能打开设置 button.addEventListener('contextmenu', (e) => { e.preventDefault(); createSettingsPanel(); }); // 添加油猴脚本管理页面的设置入口 if (window.location.href.startsWith('chrome-extension://') || window.location.href.startsWith('moz-extension://')) { // 创建设置按钮 const settingsButton = document.createElement('button'); settingsButton.textContent = 'SP2netease 设置'; settingsButton.style.cssText = ` position: fixed; top: 10px; right: 10px; z-index: 10001; padding: 10px; background-color: #E20000; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; `; settingsButton.addEventListener('click', (e) => { e.preventDefault(); createSettingsPanel(); }); document.body.appendChild(settingsButton); } // 添加左键点击功能 button.addEventListener('click', () => { if (!isDragging) { // 直接搜索最近播放的歌曲 searchDirectly(); } }); // 将按钮添加到页面 document.body.appendChild(button); }; // 直接搜索功能 - 在网易云音乐中搜索 const searchDirectly = () => { // 从存储中读取保存的Last.fm用户名 const lastfmUsername = storage.getItem('lastfmUsername'); // 调试信息 console.log('读取到的Last.fm用户名:', lastfmUsername); // 检查用户名是否存在 if (!lastfmUsername || lastfmUsername.trim() === '') { alert('请先设置Last.fm用户名'); createSettingsPanel(); return; } // 自动获取Last.fm最近播放的歌曲信息 GM_xmlhttpRequest({ method: 'GET', url: `https://www.last.fm/zh/user/${lastfmUsername}`, onload: function(response) { const parser = new DOMParser(); const doc = parser.parseFromString(response.responseText, 'text/html'); // 获取最近播放的歌曲信息 const recentTracks = doc.querySelector('.chartlist tbody tr'); if (!recentTracks) { alert('无法找到最近播放的歌曲信息'); return; } const songNameElement = recentTracks.querySelector('.chartlist-name a'); const artistElement = recentTracks.querySelector('.chartlist-artist a'); if (!songNameElement || !artistElement) { alert('无法获取歌曲信息'); return; } const songName = songNameElement.textContent.trim(); const artist = artistElement.textContent.trim(); // 构建搜索URL const searchQuery = encodeURIComponent(`${songName} ${artist}`); const searchUrl = `https://music.163.com/#/search/m/?s=${searchQuery}`; // 在新窗口打开搜索页面 window.open(searchUrl, '_blank'); }, onerror: function(error) { alert('获取歌曲信息失败: ' + error.statusText); } }); }; // 页面加载完成后创建按钮 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', createFloatingButton); } else { createFloatingButton(); } })();