Copy Audible book info for Mobilism

Format Audible book information for posting on Mobilism and copy to clipboard

  1. // ==UserScript==
  2. // @name Copy Audible book info for Mobilism
  3. // @namespace https://github.com/AbdurazaaqMohammed
  4. // @version 1.0.1
  5. // @author Abdurazaaq Mohammed
  6. // @description Format Audible book information for posting on Mobilism and copy to clipboard
  7. // @match https://www.audible.com/pd/*
  8. // @match https://images.mobilism.org/*
  9. // @match https://ezgif.com/*
  10. // @homepage https://github.com/AbdurazaaqMohammed/userscripts
  11. // @license The Unlicense
  12. // @supportURL https://github.com/AbdurazaaqMohammed/userscripts/issues
  13. // @grant GM_setValue
  14. // @grant GM_getValue
  15. // @grant GM_setClipboard
  16. // @grant GM_openInTab
  17. // ==/UserScript==
  18.  
  19. (function() {
  20. 'use strict';
  21.  
  22. const url = window.location.href;
  23. const mobilism = 'https://images.mobilism.org/';
  24.  
  25. function goToMobilism(image) {
  26. const h = image.naturalHeight;
  27. const w = image.naturalWidth;
  28. checkImageSize();
  29. if (needsResize(h, w)) {
  30. setNewRes(h/w);
  31. openTab('https://ezgif.com/resize?url=' + image);
  32. }
  33. else if (GM_getValue('needsCompress')) {
  34. openTab('https://ezgif.com/optimize?url=' + image);
  35. } else {
  36. GM_setValue('u', image);
  37. openTab(mobilism);
  38. }
  39. }
  40.  
  41. function getValue(key) {
  42. return new Promise((resolve, reject) => {
  43. try {
  44. const value = GM_getValue(key);
  45. resolve(value);
  46. } catch (error) {
  47. reject(error);
  48. }
  49. });
  50. }
  51.  
  52. function openTab(link) {
  53. try {
  54. GM_openInTab(link);
  55. } catch(e) {
  56. window.open(link, '_blank');
  57. }
  58. }
  59.  
  60. function uploadImg() {
  61. document.getElementById('imgUrl').value = GM_getValue('u');
  62. document.querySelector('#uploadbutton').click();
  63. }
  64.  
  65. function copyImageLink() {
  66. const link = document.querySelector('#codelbb');
  67. GM_setValue('i', link.value);
  68. }
  69.  
  70. function checkImageSize() {
  71. fetch(url)
  72. .then(response => {
  73. if (response.ok) {
  74. return response;
  75. }
  76. throw new Error('Network response was not ok.');
  77. })
  78. .then(response => {
  79. const contentLength = response.headers.get('Content-Length');
  80. if (contentLength > 4000000) GM_setValue('needsCompress', true);
  81. })
  82. .catch(error => console.error('Error fetching image:', error));
  83. }
  84.  
  85. function needsResize(h, w) {
  86. return h > 2499 || w > 2499;
  87. }
  88.  
  89. function setNewRes(aspectRatio) {
  90. let height, width;
  91. if (aspectRatio > 1) {
  92. width = 2499;
  93. height = Math.round(width / aspectRatio);
  94. } else {
  95. height = 2499;
  96. width = Math.round(height * aspectRatio);
  97. }
  98. GM_setValue('newHeight', height);
  99. GM_setValue('newWidth', width);
  100. }
  101.  
  102. // List of Fiction categories
  103. const fictionCategories = [
  104. "Classics", "Fantasy", "Science Fiction", "Historical", "Horror", "Humor",
  105. "LGBTQ+", "Mystery", "Thriller & Suspense", "Romantic Comedy", "Romantic Suspense",
  106. "Western", "Paranormal", "Action & Adventure", "Drama & Plays", "Anthologies & Short Stories",
  107. "Genre Fiction"
  108. ];
  109.  
  110. function isFiction(category) {
  111. // Check if the category matches any of the Fiction categories
  112. return fictionCategories.some(fiction => category.includes(fiction));
  113. }
  114.  
  115. function formatBookInfo() {
  116. const titleElement = document.querySelector('h1[data-automation-id="productTitle"]');
  117. const title = titleElement ? titleElement.innerText : 'Unknown Title';
  118. const authorElement = document.querySelector('.authorLabel a');
  119. const author = authorElement ? authorElement.innerText : 'Unknown Author';
  120. const narratorElement = document.querySelector('.narratorLabel a');
  121. const narrator = narratorElement ? narratorElement.innerText : 'Unknown Narrator';
  122. const runtimeElement = document.querySelector('li.bc-list-item.runtimeLabel');
  123. const runtime = runtimeElement ? runtimeElement.innerText : 'Unknown';
  124. const fileSize = "FileSizeHere";
  125. const summaryElement = document.querySelector('.productPublisherSummary');
  126. const summary = summaryElement ? summaryElement.innerText.replace("Publisher's summary\n\n", "") : 'No summary available.';
  127. const categoryElement = document.querySelector('.bc-chip');
  128. const category = categoryElement ? categoryElement.innerText : 'Unknown Category';
  129.  
  130. // Determine Fiction or Non-Fiction category
  131. const genrePrefix = isFiction(category) ? "Fiction" : "Non-Fiction";
  132. let formattedInfo = `[b]${title} by ${author} Narrated by ${narrator}[/b]
  133. [u]Requirements:[/u] .M4A/.M4B reader, ${fileSize} MB ${runtime}
  134. [u]Overview:[/u] ${summary}
  135. [b]Genre:[/b] Audiobooks > ${genrePrefix} > ${category}`;
  136.  
  137. goToMobilism(document.querySelector("#center-1 > div > div.hero-content.bc-pub-clearfix.bc-container.hero-overflow-visible > div > div > div > div.bc-col-responsive.bc-col-3 > div > div:nth-child(1) > img").src);
  138. getValue('i').then(value => {
  139. formattedInfo += '\n\n' + value + '\n[break]\n[u]Download Instructions:[/u]';
  140. GM_setClipboard(formattedInfo);
  141. }).catch(error => {
  142. GM_setClipboard(formattedInfo);
  143. console.error(error);
  144. });
  145.  
  146. alert('Audiobook information has been copied to clipboard!');
  147. }
  148.  
  149. if (url.endsWith(mobilism)) window.addEventListener('load', uploadImg);
  150. else if (url.endsWith('.php')) window.addEventListener('load', copyImageLink);
  151. else if (url.startsWith('https://ezgif.com/resize')) {
  152. document.querySelector(".new-height.number.text").value = GM_getValue('newHeight');
  153. document.querySelector(".new-width.number.text").value = GM_getValue('newWidth');
  154. document.getElementById('ar').selectedIndex = 2;
  155. }
  156. else if (url.includes('ezgif.com/tmp/')) goToMobilism();
  157. else {
  158. const button = document.createElement('button');
  159. button.innerText = 'Copy Formatted Info';
  160. button.style.position = 'fixed';
  161. button.style.top = '10px';
  162. button.style.right = '10px';
  163. button.style.zIndex = '9999';
  164. button.addEventListener('click', formatBookInfo);
  165. document.body.appendChild(button);
  166. GM_deleteValue('i');
  167. }
  168.  
  169. })();