Simple Suno Downloader

Simple suno music downloader

目前为 2024-04-14 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Simple Suno Downloader
  3. // @name:ru Simple Suno Downloader
  4. // @namespace https://github.com/WolfySoCute
  5. // @version 2024-04-14
  6. // @description Simple suno music downloader
  7. // @description:ru Простой загрузчик музыки с сайта suno
  8. // @author Wolfy
  9. // @match https://suno.com/*
  10. // @icon https://suno.com/favicon.ico
  11. // @grant none
  12. // @license GNU GPLv3
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17. let blobUrl;
  18.  
  19. function editButton(button, audio, node) {
  20. if (blobUrl) URL.revokeObjectURL(blobUrl);
  21.  
  22. const xhr = new XMLHttpRequest();
  23. xhr.open('GET', audio.src, true);
  24. xhr.responseType = 'blob';
  25.  
  26. xhr.onload = function() {
  27. if (xhr.status === 200) {
  28. const blob = new Blob([xhr.response], { type: 'audio/mpeg' });
  29. blobUrl = URL.createObjectURL(blob);
  30.  
  31. const authorNode = document.getElementsByClassName("css-dw5ttn")[0].childNodes[0];
  32. const titleNode = document.getElementsByClassName("css-idoyen")[0];
  33.  
  34. button.href = blobUrl;
  35. button.download = `${authorNode.textContent} - ${titleNode.textContent}.mp3`;
  36. node.appendChild(button);
  37. }
  38. };
  39.  
  40. xhr.send();
  41. }
  42.  
  43. function startScript() {
  44. const downloadButton = document.createElement("a");
  45. downloadButton.setAttribute("data-theme", "dark");
  46. downloadButton.setAttribute("aria-label", "Download");
  47. downloadButton.classList.add("chakra-button", "css-o244em");
  48. downloadButton.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" fill="#ffffff"/></svg>';
  49.  
  50. const buttonsNode = document.getElementsByClassName("css-18y9vo3")[0];
  51. const audioNode = document.getElementById("active-audio-play");
  52.  
  53. const callback = (mutationList, observer) => {
  54. for (const mutation of mutationList) {
  55. if (mutation.type === "attributes") {
  56. editButton(downloadButton, audioNode, buttonsNode)
  57. }
  58. }
  59. };
  60.  
  61. const config = { attributes: true };
  62.  
  63. const observer = new MutationObserver(callback);
  64. observer.observe(audioNode, config);
  65.  
  66. if (audioNode.src) {
  67. editButton(downloadButton, audioNode, buttonsNode)
  68. }
  69. }
  70.  
  71. setTimeout(() => {
  72. startScript();
  73. }, 2000)
  74. })();