🏠 Home 

Greasy Fork is available in English.

SoundCloud封面下载器

使用Alt+C下载SoundCloud的封面图片


安装此脚本?
// ==UserScript==
// @name         SoundCloud Cover Downloader
// @name:zh-CN   SoundCloud封面下载器
// @namespace    http://tampermonkey.net/
// @version      2024-10-09
// @description  Use Alt+C to download cover image from soundcloud
// @description:zh-CN  使用Alt+C下载SoundCloud的封面图片
// @author       Nolca
// @license      MIT
// @match        https://soundcloud.com/*
// @icon         https://soundcloud.com/favicon.ico
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @noframes
// ==/UserScript==
const DEBUG = true;
const cli = { x: 0, y: 0 };
const l = {
leaveBlankToCopy: {
"zh-CN": "留空以复制封面URL",
"en-US": "Leave Filename blank to copy cover URL"
},
fileName: {
"zh-CN": "文件名",
"en-US": "Filename"
},
useAltC: {
"zh-CN": "Alt+C下载当前封面;\n打开播放列表后,下载鼠标指向的封面",
"en-US": "Alt+C to download current cover;\nOpen playlist and download the cover under mouse cursor"
},
alwaysRename: {
"zh-CN": "总是重命名",
"en-US": "Always Rename"
},
alwaysRenameTip: {
"zh-CN": "每次按下Alt+C时,都会弹窗询问文件名",
"en-US": "Every time you press Alt+C, a prompt will ask for filename"
}
};
let LANG = GM_getValue('userLang') || navigator.language || navigator.userLanguage;
let menu_tip = GM_registerMenuCommand(
l.useAltC[LANG],
function () {
GM_unregisterMenuCommand(menu_tip);
},
{
id: 'menu_tip',
autoClose: false,
title: l.useAltC[LANG]
}
);
function menu_directDownload_click() {
GM_setValue('alwaysRename', !GM_getValue('alwaysRename'));
// GM_unregisterMenuCommand(menu_directDownload);
menu_directDownload = menu_directDownload_regist();
};
function menu_directDownload_regist() {
return GM_registerMenuCommand(
`${l.alwaysRename[LANG]}: ${GM_getValue('alwaysRename') ? '✅' : '❌'}`,
menu_directDownload_click,
{
id: 'menu_directDownload',
accessKey: 'r',
autoClose: false,
title: l.alwaysRenameTip[LANG]
}
);
};
if (GM_getValue('alwaysRename') === undefined) GM_setValue('alwaysRename', true);
var menu_directDownload = menu_directDownload_regist();
document.removeEventListener('keydown', event_keydown);
document.removeEventListener('mousemove', event_mousemove);
async function download_xhr2_blob(url, filenameDefault = "cover_soundcloud") {
let filename = filenameDefault;
if (GM_getValue('alwaysRename') === true) {
filename = prompt(`${l.leaveBlankToCopy[LANG]}:\n${url}\n\n${l.fileName[LANG]}:`, filenameDefault);
if (filename === "") {
// Copy URL to clipboard
navigator.clipboard.writeText(url.replace(/-t500x500/, '-original'));
return;
} else if (filename === null) return;
}
const res = await fetch(url);
const blob = await res.blob();
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = filename;
a.click();
URL.revokeObjectURL(a.href);
a.remove();
}
function get_coverUrl_from(span, regex = /-t50x50/) {
if (span) {
const coverUrl = span.style.backgroundImage.match(/url\("(.+)"\)/)[1];
// 将-t50x50替换为-t500x500
return coverUrl.replace(regex, '-t500x500');
} else {
console.error("span not found");
}
}
function get_wrapper_coverSpan() {
const elem = document.elementFromPoint(cli.x, cli.y);
const parentWrapper = elem.closest('div.queue__itemWrapper');
const coverPic = parentWrapper.querySelector("div > div.queueItemView__artwork > div.image.queueItemView__artworkImage > span");
return {
wrapper: parentWrapper,
span: coverPic
};
}
function event_downloader_cover() {
let author, title, coverUrl;
const elem_playlist = document.querySelector("#app > div.playControls.g-z-index-control-bar.m-visible.m-queueVisible > section > div > div.playControls__queue > div > div.queue__scrollable.g-scrollable.g-scrollable-v > div.queue__scrollableInner.g-scrollable-inner > div > div > div");
if (elem_playlist) {
// alert("playList opened");
const { wrapper, span } = get_wrapper_coverSpan();
coverUrl = get_coverUrl_from(span);
const details = wrapper.querySelector("div > div.queueItemView__details");
author = details.querySelector("div.queueItemView__meta > a.queueItemView__username").innerHTML;
title = details.querySelector("div.queueItemView__title > a").innerHTML;
} else {
// alert("playList closed");
const span = document.querySelector("#app > div.playControls.g-z-index-control-bar.m-visible > section > div > div.playControls__elements > div.playControls__soundBadge > div > a > div > span");
coverUrl = get_coverUrl_from(span);
const select = document.querySelector("#app > div.playControls.g-z-index-control-bar.m-visible > section > div > div.playControls__elements > div.playControls__soundBadge > div > div.playbackSoundBadge__titleContextContainer.sc-mr-3x");
author = select.querySelector("a").innerHTML;
title = select.querySelector("div > a > span:nth-child(2)").innerHTML;
}
const filename = `@${author} - ${title}☁️`;
console.log("event_downloader_cover: coverUrl=", coverUrl);
download_xhr2_blob(coverUrl, filename).then().catch(console.error);
}
function is_alt(lowerCase, event) {
return event.altKey && event.key === lowerCase || event.altKey && event.key === lowerCase.toUpperCase();
}
function is_alt_shift(lowerCase, event) {
return event.altKey && event.shiftKey && event.key === lowerCase || event.altKey && event.shiftKey && event.key === lowerCase.toUpperCase();
}
function event_keydown(event) {
if (is_alt('c', event)) {
event_downloader_cover();
} else if (is_alt('s', event)) {
event_downloader_song();
}
}
function event_mousemove(event) {
cli.x = event.clientX;
cli.y = event.clientY;
// console.log(cli);
}
document.addEventListener('keydown', event_keydown);
document.addEventListener('mousemove', event_mousemove);