Skip to content

Instantly share code, notes, and snippets.

@Lordmau5
Last active March 28, 2025 08:03
Show Gist options
  • Save Lordmau5/f9fbf60651c765fc61a50a27ebcf7d4a to your computer and use it in GitHub Desktop.
Save Lordmau5/f9fbf60651c765fc61a50a27ebcf7d4a to your computer and use it in GitHub Desktop.
Keygenmusic.tk Improvements
// ==UserScript==
// @name Keygenmusic.tk Improvements
// @namespace http://tampermonkey.net/
// @version 1.3.1
// @description Various extra functionality and fixes for the amazing site Keygenmusic.tk (Volume slider, Seekbar, Loop toggle, List fixes)
// @author Lordmau5
// @match https://keygenmusic.tk/
// @icon https://www.google.com/s2/favicons?sz=64&domain=keygenmusic.tk
// @grant none
// @require https://unpkg.com/[email protected]/dist/hyperlist.js
// ==/UserScript==
/*
TODO:
- add download button
- show current seekbar second when holding down and dragging, so you know where you "drop"
- try to make audio not lag when scrolling (async-ify onaudioprocess?)
^ seems to mostly be fixed?
*/
(function() {
'use strict';
let repeatCount = 0;
let sliderValue = 0.5;
let currentSong = '';
let seeking = false;
function toggleLoop() {
if (!window.watcher) return;
repeatCount = this.checked ? -1 : 0;
window.player.config.repeatCount = repeatCount;
window.player.reloadConfig(window.player.config, window.player.currentPlayingNode);
}
function onSliderInput() {
sliderValue = this.value / 100;
const slider_text = document.querySelector('#volume_slider_text');
slider_text.innerText = `VOLUME ${this.value}%`;
localStorage.setItem('slider_volume', sliderValue);
}
function updateGainElement() {
if (!window.player) return;
if (window.player.config) {
window.player.config.repeatCount = repeatCount;
}
if (window.player.gainNode) {
window.player.gainNode.gain.value = sliderValue;
}
}
function buildLoopButton() {
const div = document.createElement('div');
div.id = 'loop_control';
div.classList.add('center');
div.style = 'margin-top: 15px;';
const strong = document.createElement('strong');
strong.style = 'font-size: 19px; color: #a9b7c6;';
strong.appendChild(document.createTextNode('LOOP'));
const switchDiv = document.createElement('div');
switchDiv.classList.add('switch');
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.id = 'loop';
checkbox.classList.add('switch-check');
checkbox.onclick = toggleLoop;
const label = document.createElement('label');
label.htmlFor = 'loop';
label.classList.add('switch-label');
label.appendChild(document.createTextNode('Check'));
label.appendChild(document.createElement('span'));
switchDiv.appendChild(checkbox);
switchDiv.appendChild(label);
div.appendChild(strong);
div.appendChild(switchDiv);
return div;
}
function buildVolumeSlider() {
/* Get LocalStorage Slider Value */
const _raw_slider_volume = localStorage.getItem('slider_volume');
if (!!_raw_slider_volume) {
sliderValue = Math.max(0, parseFloat(_raw_slider_volume));
}
const div = document.createElement('div');
div.id = 'volume_control';
div.classList.add('center');
div.style = 'margin-top: 15px;';
const strong = document.createElement('strong');
strong.style = 'font-size: 19px; color: #a9b7c6;';
strong.id = 'volume_slider_text';
strong.appendChild(document.createTextNode('VOLUME 50%'));
const innerDiv = document.createElement('div');
const input = document.createElement('input');
input.style = 'width: 30%;';
input.type = 'range';
input.min = '0';
input.max = '100';
input.value = sliderValue * 100;
input.oninput = onSliderInput;
input.classList.add('volume_slider_input');
innerDiv.appendChild(input);
strong.innerText = `VOLUME ${input.value}%`;
div.appendChild(strong);
div.appendChild(innerDiv);
return div;
}
function onSeekbarInput() {
seeking = true;
}
function onSeekbarChange() {
seeking = false;
if (!window.player || !window.player.currentPlayingNode || !window.player.currentPlayingNode.modulePtr) return;
const seconds = document.querySelector('.seekbar_input').value;
window._openmpt_module_set_position_seconds(window.player.currentPlayingNode.modulePtr, seconds);
}
function onSeekbarMouseUp() {
seeking = false;
}
function buildSeekbar() {
const div = document.createElement('div');
div.id = 'seekbar';
div.classList.add('center');
div.style = 'margin-top: 15px;';
const strong = document.createElement('strong');
strong.style = 'font-size: 19px; color: #a9b7c6;';
strong.id = 'seekbar_text';
strong.appendChild(document.createTextNode('00:00 / 00:00'));
const innerDiv = document.createElement('div');
const input = document.createElement('input');
input.style = 'width: 30%;';
input.type = 'range';
input.min = '0';
input.max = '0';
input.value = 0;
input.oninput = onSeekbarInput;
input.onchange = onSeekbarChange;
input.mouseup = onSeekbarMouseUp;
input.classList.add('seekbar_input');
innerDiv.appendChild(input);
div.appendChild(strong);
div.appendChild(innerDiv);
return div;
}
function secondsToMinutes(seconds) {
seconds = Math.floor(seconds);
const minutes = Math.floor(seconds / 60);
const remaining_seconds = seconds % 60;
return `${minutes.toString().padStart(2, '0')}:${remaining_seconds.toString().padStart(2, '0')}`;
}
let times_played = 0;
function loopObserver() {
if (!window.player.currentPlayingNode || !window.player.currentPlayingNode.modulePtr) {
times_played = 0;
setTimeout(loopObserver, 100);
return;
}
// eslint-disable-next-line
const song_length = _openmpt_module_get_duration_seconds(window.player.currentPlayingNode.modulePtr);
// eslint-disable-next-line
const song_position = _openmpt_module_get_position_seconds(window.player.currentPlayingNode.modulePtr);
if (!seeking) {
document.querySelector('.seekbar_input').value = Math.floor(song_position % song_length);
}
const seekbar_text = document.querySelector('#seekbar_text');
seekbar_text.innerText = `${secondsToMinutes(song_position % song_length)} / ${secondsToMinutes(song_length)}`;
const played = Math.floor(song_position / song_length);
if (played > times_played && repeatCount === -1) {
times_played = played;
window.user.getTracksPlayed(function (num) {
const new_count = parseInt(num, 10) + 1;
window.model.write('tracks_played', new_count);
window.UI.renderTracksPlayed(new_count);
window.watcher.handleTotalPlayed();
});
}
setTimeout(loopObserver, 100);
}
function hookSearch() {
if(!window.watcher || !window.watcher.search || !window.search_input) {
setTimeout(hookSearch, 100);
return;
}
const old_search = window.watcher.search;
const hook_search = function(val) {
window.UI.renderPlaylist(window.playList.setSelected(val), val);
window.playList.setCurrentPlayList(window.UI.getShuffleBtnStatus());
};
window.watcher.search = hook_search;
window.search_input.oninput = function() {
hook_search(window.search_input.value);
};
console.log('[Hooked] window.watcher.search');
}
let playlistObject = false;
let playlistConfig = {};
let playlistSongs = [];
function hookPlaylist() {
if (!window.UI || !window.UI.renderPlaylist || !window.playList.song_lib || !window.playList.song_lib.length) {
setTimeout(hookPlaylist, 1);
return;
}
const hookVirtualList = function(playlist) {
playlistSongs = playlist;
if (window.__hookedVirtualList) {
playlistConfig.total = playlistSongs.length;
playlistObject.refresh(document.querySelector('#playlist table tbody'), playlistConfig);
return;
}
document.head.insertAdjacentHTML('beforeend', `<style>
#playlist .track {
max-width: 420px;
overflow: hidden;
white-space: nowrap;
text-overflow: clip;
}
#playlist .track_number {
min-width: 34px;
}
#playlist .heart {
position: absolute;
top: 18px;
right: 0px;
}
#playlist td.heart span {
color: #9daaaf;
}
</style>`);
const table = document.querySelector('#playlist table');
const table_body = document.createElement('tbody');
playlistConfig = {
itemHeight: 60,
total: playlistSongs.length,
useFragment: true,
overrideScrollPosition() {
return document.querySelector('.scroller').scrollTop;
},
generate(index) {
const song = playlistSongs[index];
// Outer track element
const track_element = document.createElement('tr');
track_element.classList.add('playlist_track');
track_element.setAttribute('data-path', song.path);
track_element.style.width = '100%';
if (currentSong === song.path) {
track_element.classList.add('now_playing');
}
/* Track Number */
const track_number = document.createElement('td');
track_number.classList.add('track_number');
track_number.innerText = song.n;
/* ------------ */
/* Track */
const track = document.createElement('td');
track.classList.add('track');
const author = document.createElement('span');
author.classList.add('rg');
author.innerText = song.rg;
const name = document.createElement('span');
name.classList.add('soft');
name.innerText = song.sn;
const metadata = document.createElement('span');
metadata.classList.add('mdt');
metadata.classList.add('time');
metadata.innerHTML = song.mdt || '&#8203;';
track.appendChild(author);
track.appendChild(document.createElement('br'));
track.appendChild(name);
track.appendChild(document.createElement('br'));
track.appendChild(metadata);
/* ----- */
/* Favorite */
const favorite = document.createElement('td');
favorite.setAttribute('title', 'Favorite');
favorite.classList.add('heart');
if (window.playList.isFavoriteSong(song.path)) {
favorite.classList.add('favorite');
}
const heart_span = document.createElement('span');
heart_span.innerHTML = '&#10084';
favorite.appendChild(heart_span);
/* -------- */
track_element.appendChild(track_number);
track_element.appendChild(track);
track_element.appendChild(favorite);
return track_element;
}
};
playlistObject = window.HyperList.create(table_body, playlistConfig);
table.appendChild(table_body);
window.__hookedVirtualList = true;
};
const old_renderPlaylist = window.UI.renderPlaylist;
const hook_renderPlaylist = function(playlist, listName) {
hookVirtualList(playlist);
console.log(`Loaded playlist "${listName}" with ${playlist.length} songs.`);
};
window.UI.renderPlaylist = hook_renderPlaylist;
const table = document.querySelector('#playlist table');
if (table.firstChild) {
while(table.firstChild) {
table.firstChild.remove();
}
}
window.UI.renderPlaylist(window.playList.song_lib, '');
window.playList.setSelected('');
const old_scrollToSongInPlaylist = window.UI.scrollToSongInPlaylist;
const hook_scrollToSongInPlaylist = function(song) {
let id = -1;
for (let i = 0; i < window.playList.selected.length; i++) {
const _s = window.playList.selected[i];
if (song === _s.path) {
id = i;
break;
}
}
if (id === -1) return;
window.$scroller.scrollTop(id * 60);
};
window.UI.scrollToSongInPlaylist = hook_scrollToSongInPlaylist;
const old_updateSongInfo = window.watcher.updateSongInfo;
const hook_updateSongInfo = function(song) {
old_updateSongInfo(song);
currentSong = song;
document.querySelector('.seekbar_input').value = 0;
};
window.watcher.updateSongInfo = hook_updateSongInfo;
const observer = new MutationObserver(function(mutationsList, observer) {
for(const mutation of mutationsList) {
if (mutation.type === 'childList') {
for (const tr of mutation.addedNodes) {
if(!tr.hasAttribute('data-path')) continue;
if(tr.getAttribute('data-path') === currentSong) {
tr.classList.add('now_playing');
}
else {
tr.classList.remove('now_playing');
}
}
}
}
});
observer.observe(document.querySelector('#playlist table tbody'), {
attributes: false,
childList: true,
subtree: false
});
}
function hookShuffle() {
if (!window.shuffle || !window.playList || !window.UI) {
setTimeout(hookShuffle, 1);
return;
}
window.shuffle.addEventListener('change', () => {
localStorage.setItem('shuffle', window.shuffle.checked);
});
/* Get LocalStorage Shuffle Value */
const _shuffle_status = localStorage.getItem('shuffle');
if (!!_shuffle_status) {
window.shuffle.checked = _shuffle_status === 'true';
window.playList.setCurrentPlayList(window.UI.getShuffleBtnStatus());
}
}
function inject() {
const player_container = document.querySelector('#player .container');
if (!player_container || !window.ChiptuneJsPlayer) {
setTimeout(inject, 100);
return;
}
// Add new method to this bad boy
window.ChiptuneJsPlayer.prototype.reloadConfig = function(config, processNode) {
if (!processNode || !processNode.modulePtr) return;
// eslint-disable-next-line
_openmpt_module_set_repeat_count(processNode.modulePtr, config.repeatCount);
// eslint-disable-next-line
_openmpt_module_set_render_param(processNode.modulePtr, OPENMPT_MODULE_RENDER_STEREOSEPARATION_PERCENT, config.stereoSeparation);
// eslint-disable-next-line
_openmpt_module_set_render_param(processNode.modulePtr, OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH, config.interpolationFilter);
};
const old_ChiptuneJsPlayer_play = window.ChiptuneJsPlayer.prototype.play;
window.ChiptuneJsPlayer.prototype.play = function(buffer) {
old_ChiptuneJsPlayer_play.call(this, buffer);
document.querySelector('.seekbar_input').max = Math.floor(window._openmpt_module_get_duration_seconds(window.player.currentPlayingNode.modulePtr));
};
// Hook search
hookSearch();
// Hook playlist
hookPlaylist();
// Observe loops
loopObserver();
// Hook shuffle button
hookShuffle();
// Add Loop Button
player_container.appendChild(buildLoopButton());
// Add Volume Slider
player_container.appendChild(buildVolumeSlider());
// Add Seekbar
player_container.appendChild(buildSeekbar());
setInterval(updateGainElement, 10);
}
setTimeout(inject, 100);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment