Files
skribbl-autosave/prod.user.js

202 lines
7.1 KiB
JavaScript

// ==UserScript==
// @name Skribbl.io Auto Drawing Downloader
// @namespace http://tampermonkey.net/
// @version 1.2
// @description type shit
// @author ZStrike
// @match *://skribbl.io/*
// @license GPL
// @grant none
// @source https://git.zstrike.dev/zstrike/skribbl-autosave
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
class config {
constructor() {
if (window.localStorage.getItem("autodl_config") == null) {
this.conf = {"toggle":"1","format":"png","version":"1.2"}
} else {
this.conf = JSON.parse(window.localStorage.getItem("autodl_config"))
}
this.toggElm = document.querySelector("#select-autodl_toggle")
this.formElm = document.querySelector("#select-autodl_format")
this.toggElm.value = this.conf.toggle
this.formElm.value = this.conf.format
this.toggElm.onchange, this.formElm.onchange = this.update
}
update = () => {
this.conf.toggle = this.toggElm.value
this.conf.format = this.formElm.value
localStorage.setItem("autodl_config",JSON.stringify(this.conf))
}
}
function startRecording() {
const canvas = document.querySelector("canvas");
if (!canvas) {
console.warn("Canvas not found, can't start recording");
return;
}
try {
const stream = canvas.captureStream(10);
mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm' });
recordedChunks = [];
mediaRecorder.ondataavailable = function(e) {
if (e.data.size > 0) {
recordedChunks.push(e.data);
}
};
mediaRecorder.start();
console.log("[Hook] Recording started...");
} catch (err) {
console.error("[Hook] Error starting recording:", err);
}
}
function stopRecordingAndDownload(title) {
if (!mediaRecorder || mediaRecorder.state === 'inactive') return;
mediaRecorder.onstop = function() {
const blob = new Blob(recordedChunks, { type: 'video/webm' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = title;
document.body.appendChild(a);
a.click();
//cleanup stuff
setTimeout(() => {
document.body.removeChild(a);
URL.revokeObjectURL(url);
}, 100);
};
mediaRecorder.stop();
}
window.addEventListener("DOMContentLoaded", (ev) => {
document.querySelector(".modal-container-settings").innerHTML += `<div class="group" id="autodlmenu"><div class="title"><div class="icon misc"></div><div class="desc" data-translate="text">Auto-Downloader</div></div><div class="item"><div class="key" data-translate="text">Feature Toggle</div><select id="select-autodl_toggle"><option value="0">Disabled<option value="1">Enabled</select><div class="key" data-translate="text">Download Type</div><select id="select-autodl_format"><option value="webm">Animated (.WEBM)<option value="png">Static (.PNG)</select></div></div>`
window.autodlconfig = new config()
for (const element of document.querySelectorAll('[class^="select-autodl_"]')) {
element.onchange = window.autodlconfig.update
}
})
const OriginalWebSocket = window.WebSocket;
const players = new Map();
let currentDrawerId = null;
let mediaRecorder = null;
let recordedChunks = [];
function downloadImage(blob,name) {
const downloadAnchor = document.createElement("a");
downloadAnchor.id = "autodl-trigger";
downloadAnchor.style.display = "none";
downloadAnchor.href = URL.createObjectURL(blob);
downloadAnchor.download = name;
document.body.appendChild(downloadAnchor);
downloadAnchor.click();
downloadAnchor.remove();
}
window.WebSocket = function(...args) {
const ws = new OriginalWebSocket(...args);
ws.addEventListener('message', function(event) {
if (typeof event.data !== 'string') return;
if (!event.data.startsWith('42')) return;
try {
const payload = JSON.parse(event.data.slice(2));
if (payload[0] === 'data') {
const packet = payload[1];
if (packet.id === 10) {
players.clear();
const users = packet.data.users;
if (Array.isArray(users)) {
users.forEach(user => {
players.set(user.id, user.name);
});
}
// fix mid-game joining
const currentState = packet.data.state;
if (currentState && currentState.id === 4) {
currentDrawerId = currentState.data.id;
if (window.autodlconfig.conf.toggle == true && window.autodlconfig.conf.format == "webm") {
startRecording()
}
}
}
if (packet.id === 1) {
players.set(packet.data.id, packet.data.name);
}
if (packet.id === 11) { // game state updates
const gameState = packet.data;
if (gameState && gameState.id === 4) { // new turn
currentDrawerId = gameState.data.id;
if (window.autodlconfig.conf.toggle == true && window.autodlconfig.conf.format == "webm") {
startRecording()
}
}
if (gameState && gameState.id === 5) { // end turn
const turnData = gameState.data;
const drawerName = players.get(currentDrawerId) || 'Unknown Player';
console.log(`Drawer: ${drawerName} (ID: ${currentDrawerId})`);
console.log('Word:', turnData.word);
if (window.autodlconfig.conf.toggle == true) {
if (window.autodlconfig.conf.format == "png") {
document.querySelector("canvas").toBlob((a) => {
downloadImage(a,`${turnData.word} by ${drawerName}`)
});
} else {
stopRecordingAndDownload(`${turnData.word} by ${drawerName}.webm`)
}
}
}
}
}
} catch (e) {
console.error(e)
}
});
return ws;
};
})();