Rhythm Plus Export/Import maps

export/import

  1. // ==UserScript==
  2. // @name Rhythm Plus Export/Import maps
  3. // @namespace http://tampermonkey.net/
  4. // @version 2024-07-14
  5. // @description export/import
  6. // @author qtpq
  7. // @match https://rhythm-plus.com/editor/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=rhythm-plus.com
  9. // @license MIT
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. const id = window.location.href.split("/")[4]
  17. const postUrl = 'https://api.rhythm-plus.com/api/v1/sheet/update?sheetId=' + id
  18. const getUrl = 'https://api.rhythm-plus.com/api/v1/sheet/get?sheetId=' + id
  19.  
  20. let mapDataImport = {
  21. "id": id,
  22. "mapping": null,
  23. "visibility":"private",
  24. "length":0,
  25. "noteCount":0
  26. }
  27.  
  28.  
  29. let mapDataImportBool = false
  30.  
  31. let mapDataExport
  32.  
  33. const originalFetch = window.fetch
  34.  
  35. //create custom fetch
  36. window.fetch = function(url, options) {
  37. console.log("a")
  38. console.log(url, options)
  39. if (url === postUrl && options.method === "post" && mapDataImportBool) {
  40. const Header = new Headers(options.headers)
  41. return fetch(url, {
  42. method: "POST",
  43. headers: Header,
  44. body: JSON.stringify(mapDataImport)
  45. })
  46.  
  47. }
  48. else if (url === getUrl && options.method === "get") {
  49. originalFetch(url, options).then(response => {
  50. return response.json().then(json => {
  51. mapDataExport = json
  52. return json
  53. })
  54. })
  55. }
  56.  
  57. return originalFetch(url, options)
  58. }
  59. function waitToolbar(callback) {
  60. var element = document.getElementsByClassName("toolbar")[0]
  61. if (element) {
  62. callback(element)
  63. }
  64. else {
  65. setTimeout(function() {
  66. waitToolbar(callback)
  67. }, 500)
  68. }
  69. }
  70.  
  71. waitToolbar(function(toolbar) {
  72. let exportDiv = document.createElement("div")
  73. exportDiv.textContent = "Export"
  74. exportDiv.className = "exportDiv"
  75.  
  76. let importDiv = document.createElement("div")
  77. importDiv.textContent = "Import"
  78. importDiv.className = "importDiv"
  79.  
  80.  
  81. let styles = window.getComputedStyle(toolbar.children[2])
  82. for (let prop of styles) {
  83. importDiv.style.setProperty(prop, styles.getPropertyValue(prop))
  84. exportDiv.style.setProperty(prop, styles.getPropertyValue(prop))
  85. }
  86.  
  87. toolbar.appendChild(importDiv)
  88. toolbar.appendChild(exportDiv)
  89.  
  90. exportDiv.addEventListener('click', function() {
  91.  
  92. let file = new Blob([mapDataExport.mapping], {type: "text/plain"})
  93. let a = document.createElement("a"), url = URL.createObjectURL(file)
  94. a.href = url
  95. a.download = "map.ryp"
  96. document.body.appendChild(a)
  97. a.click()
  98. document.body.removeChild(a)
  99. window.URL.revokeObjectURL(url)
  100. })
  101.  
  102.  
  103. importDiv.addEventListener("click", function() {
  104. let fileInput = document.createElement("input")
  105. fileInput.type = "file"
  106. fileInput.accept = ".ryp"
  107.  
  108. fileInput.onchange = function(event) {
  109. var file = event.target.files[0]
  110. if (file) {
  111. let fileContent = new FileReader()
  112. fileContent.onload = function(fileContent) {
  113. mapDataImport.mapping = fileContent.target.result
  114. mapDataImportBool = true
  115. document.body.removeChild(fileInput)
  116. alert("Loaded map! Press save and refresh the page to view.")
  117. }
  118. fileContent.readAsText(file)
  119. }
  120. }
  121. document.body.appendChild(fileInput)
  122. fileInput.click()
  123.  
  124. })
  125. })
  126.  
  127. })();