Music Player for Open Directories

A full-page music player with a modern interface, including download buttons, time display, and interaction banners.

  1. // ==UserScript==
  2. // @name Music Player for Open Directories
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.2
  5. // @description A full-page music player with a modern interface, including download buttons, time display, and interaction banners.
  6. // @author GhostyTongue
  7. // @match *://*/*
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. var e, t, n = document.links, i = [], o = 0;
  16. for (t in n) {
  17. var a = n[t].toString().toUpperCase();
  18. if (a.indexOf("JAVASCRIPT:") !== 0 && (a.indexOf(".MP3") !== -1 || a.indexOf(".FLAC") !== -1 || a.indexOf(".OGG") !== -1 || a.indexOf(".WAV") !== -1)) {
  19. i.push(n[t]);
  20. }
  21. }
  22.  
  23. if (i.length > 0) {
  24. var d = x("div", "player-container", "", "", ""),
  25. header = x("div", "player-header", "", "", ""),
  26. parentButton = x("button", "parent-button", "Parent Directory", "", function() {
  27. window.location.href = "../";
  28. }),
  29. title = x("div", "player-title", "Music Player", "", ""),
  30. r = x("div", "playing", "", "", ""),
  31. p = x("div", "progressbar", "", "", function(t) {
  32. var n = t.clientX;
  33. n /= window.innerWidth;
  34. e.currentTime = e.duration * n;
  35. }),
  36. l = x("div", "progress", "", "", ""),
  37. timeDisplay = x("div", "time-display", "0:00", "", "");
  38. p.appendChild(l);
  39. r.appendChild(p);
  40. r.appendChild(timeDisplay);
  41.  
  42. header.appendChild(parentButton);
  43. header.appendChild(title);
  44. d.appendChild(header);
  45.  
  46. var s = x("div", "songname", "", "", "");
  47. r.appendChild(s);
  48.  
  49. var u = x("div", "buttons", "", "", "");
  50. var playPauseButton = x("button", "control-button", "⏯", "", function() {
  51. e.paused ? (e.play(), this.innerHTML = "⏯") : (e.pause(), this.innerHTML = "▶️");
  52. showBanner(e.paused ? "Paused" : "Playing");
  53. });
  54. u.appendChild(playPauseButton);
  55. u.appendChild(x("button", "control-button", "⏮", "", y));
  56. u.appendChild(x("button", "control-button", "⏭", "", C));
  57. u.appendChild(x("button", "control-button", "🔀", "", function() {
  58. o = Math.floor(Math.random() * i.length);
  59. f();
  60. }));
  61. r.appendChild(u);
  62. d.appendChild(r);
  63.  
  64. var c = x("ul", "playlist", "", "", "");
  65. for (var songIndex in i) {
  66. var h = decodeURIComponent(unescape(i[songIndex].href)),
  67. li = x("li", "playlist-item", h.substring(h.lastIndexOf("/") + 1), songIndex, function() {
  68. o = parseInt(this.getAttribute("data"));
  69. f();
  70. }),
  71. downloadButton = x("a", "download-button", "Download", "", function(e) {
  72. e.stopPropagation();
  73. });
  74. downloadButton.href = h;
  75. downloadButton.download = h.substring(h.lastIndexOf("/") + 1);
  76. li.appendChild(downloadButton);
  77. c.appendChild(li);
  78. }
  79. d.appendChild(c);
  80.  
  81. var g = x("style", "", "", "", "");
  82. g.innerHTML = `
  83. .player-container {
  84. position: fixed;
  85. top: 0;
  86. bottom: 0;
  87. left: 0;
  88. right: 0;
  89. background-color: #282c34;
  90. color: white;
  91. font-family: Arial, sans-serif;
  92. display: flex;
  93. flex-direction: column;
  94. justify-content: space-between;
  95. z-index: 1000;
  96. }
  97. .player-header {
  98. display: flex;
  99. justify-content: center;
  100. padding: 10px;
  101. background-color: #20232a;
  102. border-bottom: 1px solid #444;
  103. }
  104. .parent-button {
  105. position: absolute;
  106. left: 10px;
  107. background-color: #61dafb;
  108. border: none;
  109. color: #282c34;
  110. padding: 10px 20px;
  111. cursor: pointer;
  112. font-weight: bold;
  113. }
  114. .player-title {
  115. font-size: 2em;
  116. margin: auto;
  117. text-align: center;
  118. }
  119. .playing {
  120. padding: 20px;
  121. }
  122. .progressbar {
  123. position: relative;
  124. height: 20px;
  125. background-color: #444;
  126. border-radius: 10px;
  127. margin-bottom: 10px;
  128. cursor: pointer;
  129. }
  130. .progress {
  131. position: absolute;
  132. height: 100%;
  133. background-color: #61dafb;
  134. border-radius: 10px;
  135. }
  136. .time-display {
  137. text-align: center;
  138. font-size: 1em;
  139. margin-bottom: 20px;
  140. }
  141. .songname {
  142. margin-bottom: 20px;
  143. text-align: center;
  144. font-size: 1.5em;
  145. white-space: nowrap;
  146. overflow: hidden;
  147. text-overflow: ellipsis;
  148. }
  149. .buttons {
  150. text-align: center;
  151. margin-bottom: 20px;
  152. }
  153. .control-button {
  154. background: none;
  155. border: none;
  156. color: #61dafb;
  157. font-size: 3em;
  158. cursor: pointer;
  159. margin: 0 20px;
  160. }
  161. .playlist {
  162. flex: 1;
  163. overflow-y: auto;
  164. background-color: #20232a;
  165. padding: 20px;
  166. list-style: none;
  167. margin: 0;
  168. }
  169. .playlist-item {
  170. padding: 10px;
  171. cursor: pointer;
  172. border-bottom: 1px solid #444;
  173. font-size: 1.2em;
  174. display: flex;
  175. justify-content: space-between;
  176. align-items: center;
  177. }
  178. .playlist-item:hover {
  179. background-color: #61dafb;
  180. color: #282c34;
  181. }
  182. .download-button {
  183. background-color: #61dafb;
  184. border: none;
  185. color: #282c34;
  186. padding: 5px 10px;
  187. cursor: pointer;
  188. font-size: 0.9em;
  189. text-decoration: none;
  190. border-radius: 5px;
  191. }
  192. .banner {
  193. position: fixed;
  194. bottom: 20px;
  195. left: 50%;
  196. transform: translateX(-50%);
  197. background-color: #61dafb;
  198. color: #282c34;
  199. padding: 10px 20px;
  200. border-radius: 5px;
  201. display: none;
  202. font-size: 1.2em;
  203. z-index: 1001;
  204. transition: opacity 0.5s;
  205. }
  206. `;
  207. d.appendChild(g);
  208.  
  209. var banner = x("div", "banner", "", "", "");
  210. d.appendChild(banner);
  211.  
  212. var m = document.createElement("meta"),
  213. b = document.createAttribute("name");
  214. b.value = "viewport";
  215. m.setAttributeNode(b);
  216. b = document.createAttribute("content");
  217. b.value = "width=device-width, initial-scale=1";
  218. m.setAttributeNode(b);
  219. document.head.appendChild(m);
  220. document.body.innerHTML = "";
  221. document.body.appendChild(d);
  222.  
  223. (e = new Audio()).addEventListener("ended", C, !1);
  224. v();
  225. f();
  226. navigator.mediaSession.setActionHandler("previoustrack", y);
  227. navigator.mediaSession.setActionHandler("nexttrack", C);
  228.  
  229. document.addEventListener("keydown", function(event) {
  230. if (event.code === "Space") {
  231. event.preventDefault();
  232. playPauseButton.click();
  233. }
  234. });
  235. }
  236.  
  237. function f() {
  238. e.src = i[o];
  239. e.play();
  240. var t = decodeURIComponent(i[o].href);
  241. s.innerHTML = t.substring(t.lastIndexOf("/") + 1);
  242. navigator.mediaSession.metadata = new MediaMetadata({
  243. title: s.innerHTML
  244. });
  245. showBanner("Playing");
  246. }
  247.  
  248. function x(e, t, n, i, o) {
  249. var a = document.createElement(e);
  250. t !== "" && a.classList.add(t);
  251. var d = document.createAttribute("data");
  252. d.value = i;
  253. a.setAttributeNode(d);
  254. a.appendChild(document.createTextNode(n));
  255. a.onclick = o;
  256. return a;
  257. }
  258.  
  259. function v() {
  260. l.style.width = e.currentTime / e.duration * 100 + "%";
  261. timeDisplay.innerHTML = formatTime(e.currentTime) + " / " + formatTime(e.duration);
  262. requestAnimationFrame(v);
  263. }
  264.  
  265. function formatTime(seconds) {
  266. var minutes = Math.floor(seconds / 60);
  267. var seconds = Math.floor(seconds % 60);
  268. return minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
  269. }
  270.  
  271. function y() {
  272. o > 0 ? o-- : o = i.length - 1;
  273. f();
  274. }
  275.  
  276. function C() {
  277. o < i.length - 1 ? o++ : o = 0;
  278. f();
  279. }
  280.  
  281. function showBanner(message) {
  282. banner.innerHTML = message;
  283. banner.style.display = "block";
  284. setTimeout(function() {
  285. banner.style.opacity = 0;
  286. setTimeout(function() {
  287. banner.style.display = "none";
  288. banner.style.opacity = 1;
  289. }, 500);
  290. }, 2000);
  291. }
  292. })();