Advertisement
Guest User

Untitled

a guest
Jan 20th, 2020
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.88 KB | None | 0 0
  1. async function sleep(ms) {
  2. return new Promise((r) => setTimeout(r, ms))
  3. }
  4. const waitMaxTries = 100
  5. async function waitForPopup(open) {
  6. for (let tries = 0; tries < waitMaxTries; tries++) {
  7. await sleep(100)
  8. if (open === !!(jQuery('.modal-dialog').length)) {
  9. break
  10. }
  11. }
  12. }
  13. async function editScrobble(form, newAttributes = {}) {
  14. const $form = jQuery(form)
  15. $form.find('button').click()
  16. await waitForPopup(true)
  17. Object.entries(newAttributes).forEach(([key, value]) => {
  18. jQuery('#id_' + key).val(value)
  19. $form.find(`[name = "${key}"]`).val(value)
  20. })
  21. jQuery('.modal-body [type="submit"]').click()
  22. await waitForPopup(false)
  23. }
  24. function scrobbleHasChange(form, newAttributes = {}) {
  25. const $form = jQuery(form)
  26. for (let attribute of Object.entries(newAttributes)) {
  27. const [key, value] = attribute
  28. const $input = $form.find(`[name="${key}"]`)
  29. if (!$input.length || $input.val().toLowerCase() !== value.toLowerCase()) {
  30. return true
  31. }
  32. }
  33. return false
  34. }
  35. function getNumPages() {
  36. return parseInt(jQuery('.pagination-list > .pagination-page:nth(-1)').text().trim())
  37. }
  38. function getCurrentPage() {
  39. return parseInt(jQuery('.pagination-list > [aria-current="page"]').text().trim())
  40. }
  41. async function setPage(n) {
  42. const currentPage = getCurrentPage()
  43. if (!currentPage || currentPage === n) {
  44. return
  45. }
  46. jQuery(`[href$="?page=${n}"]:first`).click()
  47. for (let tries = 0; tries < waitMaxTries; tries++) {
  48. await sleep(100)
  49. if (jQuery('.loading-indicator-loading').length) {
  50. break
  51. }
  52. }
  53. for (let tries = 0; tries < waitMaxTries; tries++) {
  54. await sleep(100)
  55. if (!jQuery('.loading-indicator-loading').length) {
  56. break
  57. }
  58. }
  59.  
  60. // The event listeners on the hidden forms are not initialized for an unknown amount of time after the page is done loading
  61. await sleep(1000)
  62. }
  63. let editScrobblesBatchInProgress = false
  64. async function editScrobblesBatch(newAttributes = {}) {
  65. if (editScrobblesBatchInProgress) {
  66. alert("There is a batch edit already in progress, canceling")
  67. }
  68. if (!confirm(labelFromAttributes(newAttributes) + "\n\nContinue?")) {
  69. return
  70. }
  71. editScrobblesBatchInProgress = true
  72. const lastPage = getNumPages() || 1
  73. for (let page = lastPage; page >= 1; page--) {
  74. await setPage(page)
  75. const forms = jQuery('[action*="/library/edit"]').toArray().filter((form) => {
  76. return scrobbleHasChange(form, newAttributes)
  77. })
  78. for (let form of forms) {
  79. await editScrobble(form, newAttributes)
  80. }
  81. }
  82. if (confirm('Batch edit completed!\n\nReload?')) {
  83. window.location.reload()
  84. return
  85. }
  86. editScrobblesBatchInProgress = false
  87. }
  88. function getAttributesFromModal() {
  89. const res = {}
  90. jQuery('.modal-body input[type=text]:visible').toArray().forEach((input) => {
  91. res[input.name] = input.value
  92. })
  93. return res
  94. }
  95. function labelFromAttributes(newAttributes) {
  96. const res = []
  97. return Object.entries(newAttributes).map(([key, value]) => {
  98. return `${key.split('_').slice(0, -1).map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ')}: ${value}`
  99. }).join('\n')
  100. }
  101. function injectButton() {
  102. injectCSS()
  103. const $cancel = jQuery('.modal-body .js-close')
  104. const $applyToAll = $cancel.clone()
  105. $applyToAll.text('Apply To All')
  106. $applyToAll.addClass('apply-to-all')
  107. $applyToAll.css({
  108. color: 'white',
  109. })
  110. $applyToAll.click(function(e) {
  111. e.preventDefault()
  112. editScrobblesBatch(getAttributesFromModal())
  113. return false
  114. })
  115. $applyToAll.insertBefore($cancel)
  116. }
  117.  
  118. let injectedCSS = false
  119. function injectCSS() {
  120. if (injectedCSS) {
  121. return
  122. }
  123. var css = `
  124. .apply-to-all {
  125. color: white;
  126. background-color: rgb(34, 34, 34);
  127. }
  128. .apply-to-all:hover {
  129. color: white;
  130. background-color: rgb(20, 20, 20) !important;
  131. }
  132. `;
  133. var style = document.createElement('style');
  134.  
  135. if (style.styleSheet) {
  136. style.styleSheet.cssText = css;
  137. } else {
  138. style.appendChild(document.createTextNode(css));
  139. }
  140.  
  141. document.getElementsByTagName('head')[0].appendChild(style);
  142. injectedCSS = true
  143. }
  144. function init() {
  145. jQuery('body').on('click', '[action*="/library/edit"] button:not(.js-close)', async function() {
  146. if (jQuery(this).closest('.modal-body').length) {
  147. return
  148. }
  149. if (editScrobblesBatchInProgress) {
  150. return
  151. }
  152. await waitForPopup(true)
  153. injectButton()
  154. })
  155. }
  156. if (window.jQuery) {
  157. init()
  158. } else {
  159. window.onload = init
  160. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement