Drawaria Canvas Text Writer Safe Version

Write text on the Drawaria canvas using WebSockets

  1. // ==UserScript==
  2. // @name Drawaria Canvas Text Writer Safe Version
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description Write text on the Drawaria canvas using WebSockets
  6. // @author YouTubeDrawaria
  7. // @include https://drawaria.online/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
  9. // @license MIT
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // Adding Text Input and Button
  17. function addTextInput() {
  18. let container = document.createElement('div');
  19. container.style.position = 'fixed';
  20. container.style.top = '692.984px'; // Ajusta la posición vertical
  21. container.style.left = '165.629px'; // Ajusta la posición horizontal
  22. container.style.transform = 'translateX(-50%)';
  23. container.style.zIndex = 1000;
  24. container.style.background = 'linear-gradient(135deg, #003366, #0099cc)';
  25. container.style.padding = '20px';
  26. container.style.borderRadius = '10px';
  27. container.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.2)';
  28. container.style.display = 'flex';
  29. container.style.flexDirection = 'column';
  30. container.style.alignItems = 'center';
  31. container.style.cursor = 'move';
  32.  
  33. let title = document.createElement('h3');
  34. title.textContent = 'Canvas Text Writer';
  35. title.style.margin = '0';
  36. title.style.paddingBottom = '10px';
  37. title.style.borderBottom = '1px solid #555';
  38. title.style.width = '100%';
  39. title.style.textAlign = 'center';
  40. title.style.color = 'white';
  41. container.appendChild(title);
  42.  
  43. let toggleButton = document.createElement('div');
  44. toggleButton.innerHTML = '▲'; // Up arrow (cerrado por defecto)
  45. toggleButton.style.cursor = 'pointer';
  46. toggleButton.style.fontSize = '20px';
  47. toggleButton.style.color = 'white';
  48. toggleButton.style.marginBottom = '10px';
  49. toggleButton.addEventListener('click', () => {
  50. let content = container.querySelector('.content');
  51. if (content.style.display === 'none') {
  52. content.style.display = 'flex';
  53. toggleButton.innerHTML = '▼'; // Down arrow
  54. } else {
  55. content.style.display = 'none';
  56. toggleButton.innerHTML = '▲'; // Up arrow
  57. }
  58. });
  59. container.appendChild(toggleButton);
  60.  
  61. let innerContainer = document.createElement('div');
  62. innerContainer.className = 'content';
  63. innerContainer.style.background = 'rgba(255, 255, 255, 0.2)';
  64. innerContainer.style.padding = '20px';
  65. innerContainer.style.borderRadius = '10px';
  66. innerContainer.style.width = '100%';
  67. innerContainer.style.display = 'none'; // Cerrado por defecto
  68. innerContainer.style.flexDirection = 'column';
  69. innerContainer.style.alignItems = 'center';
  70.  
  71. let wordList = document.createElement('div');
  72. wordList.style.maxHeight = '150px';
  73. wordList.style.overflowY = 'auto';
  74. wordList.style.margin = '10px 0';
  75. wordList.style.width = 'calc(100% - 20px)';
  76. wordList.style.border = '1px solid #ccc';
  77. wordList.style.borderRadius = '5px';
  78. wordList.style.padding = '10px';
  79. wordList.style.background = 'white';
  80.  
  81. let words = ['Hello', 'World', 'Draw', 'Canvas', 'Text', 'Write', 'Send', 'Clear', 'Join', 'Room'];
  82. let selectedWord = null;
  83.  
  84. words.forEach(word => {
  85. let checkbox = document.createElement('input');
  86. checkbox.type = 'checkbox';
  87. checkbox.value = word;
  88. checkbox.style.marginRight = '10px';
  89. checkbox.addEventListener('change', () => {
  90. if (checkbox.checked) {
  91. selectedWord = word;
  92. wordList.querySelectorAll('input[type="checkbox"]').forEach(cb => {
  93. if (cb !== checkbox) {
  94. cb.checked = false;
  95. }
  96. });
  97. } else {
  98. selectedWord = null;
  99. }
  100. });
  101.  
  102. let label = document.createElement('label');
  103. label.appendChild(checkbox);
  104. label.appendChild(document.createTextNode(word));
  105. label.style.display = 'block';
  106. label.style.marginBottom = '5px';
  107.  
  108. wordList.appendChild(label);
  109. });
  110.  
  111. let fontSelect = document.createElement('select');
  112. fontSelect.style.margin = '10px 0';
  113. fontSelect.style.padding = '10px';
  114. fontSelect.style.borderRadius = '5px';
  115. fontSelect.style.border = '1px solid #ccc';
  116. fontSelect.style.width = 'calc(100% - 20px)';
  117. fontSelect.innerHTML = `
  118. <option value="Arial">Arial</option>
  119. <option value="Ravie">Ravie</option>
  120. <option value="Courier">Courier</option>
  121. <option value="Magneto">Magneto</option>
  122. <option value="Papyrus">Papyrus</option>
  123. <option value="Script MT Bold">Script MT Bold</option>
  124. <option value="Algerian">Algerian</option>
  125. <option value="Segoe Print">Segoe Print</option>
  126. `;
  127.  
  128. let pixelSizeLabel = document.createElement('div');
  129. pixelSizeLabel.textContent = 'Pixel Size: 30';
  130. pixelSizeLabel.style.margin = '10px 0';
  131. pixelSizeLabel.style.color = 'white';
  132.  
  133. let pixelSizeSlider = document.createElement('input');
  134. pixelSizeSlider.type = 'range';
  135. pixelSizeSlider.min = '10';
  136. pixelSizeSlider.max = '30';
  137. pixelSizeSlider.value = '30';
  138. pixelSizeSlider.style.margin = '10px 0';
  139. pixelSizeSlider.style.width = 'calc(100% - 20px)';
  140. pixelSizeSlider.addEventListener('input', (event) => {
  141. pixelSizeLabel.textContent = `Pixel Size: ${event.target.value}`;
  142. });
  143.  
  144. let xPositionLabel = document.createElement('div');
  145. xPositionLabel.textContent = 'Horizontal Position: 0';
  146. xPositionLabel.style.margin = '10px 0';
  147. xPositionLabel.style.color = 'white';
  148.  
  149. let xPositionSlider = document.createElement('input');
  150. xPositionSlider.type = 'range';
  151. xPositionSlider.min = '0';
  152. xPositionSlider.max = '100';
  153. xPositionSlider.value = '0';
  154. xPositionSlider.style.margin = '10px 0';
  155. xPositionSlider.style.width = 'calc(100% - 20px)';
  156. xPositionSlider.addEventListener('input', (event) => {
  157. xPositionLabel.textContent = `Horizontal Position: ${event.target.value}`;
  158. });
  159.  
  160. let yPositionLabel = document.createElement('div');
  161. yPositionLabel.textContent = 'Vertical Position: 0';
  162. yPositionLabel.style.margin = '10px 0';
  163. yPositionLabel.style.color = 'white';
  164.  
  165. let yPositionSlider = document.createElement('input');
  166. yPositionSlider.type = 'range';
  167. yPositionSlider.min = '0';
  168. yPositionSlider.max = '100';
  169. yPositionSlider.value = '0';
  170. yPositionSlider.style.margin = '10px 0';
  171. yPositionSlider.style.width = 'calc(100% - 20px)';
  172. yPositionSlider.addEventListener('input', (event) => {
  173. yPositionLabel.textContent = `Vertical Position: ${event.target.value}`;
  174. });
  175.  
  176. let sendButton = document.createElement('button');
  177. sendButton.textContent = 'Send Text';
  178. sendButton.style.padding = '10px';
  179. sendButton.style.borderRadius = '5px';
  180. sendButton.style.border = 'none';
  181. sendButton.style.background = 'linear-gradient(to bottom, white, #d3d3d3)';
  182. sendButton.style.color = '#003366';
  183. sendButton.style.cursor = 'pointer';
  184. sendButton.style.width = 'calc(100% - 20px)';
  185. sendButton.style.marginBottom = '10px';
  186. sendButton.addEventListener('click', () => {
  187. if (selectedWord) {
  188. drawTextOnCanvas(selectedWord, fontSelect.value, parseInt(pixelSizeSlider.value), parseInt(xPositionSlider.value), parseInt(yPositionSlider.value));
  189. }
  190. });
  191.  
  192. let clearCanvasButton = document.createElement('button');
  193. clearCanvasButton.textContent = 'Clear Canvas';
  194. clearCanvasButton.style.padding = '10px';
  195. clearCanvasButton.style.borderRadius = '5px';
  196. clearCanvasButton.style.border = 'none';
  197. clearCanvasButton.style.background = 'linear-gradient(to bottom, white, #d3d3d3)';
  198. clearCanvasButton.style.color = '#003366';
  199. clearCanvasButton.style.cursor = 'pointer';
  200. clearCanvasButton.style.width = 'calc(100% - 20px)';
  201. clearCanvasButton.style.marginBottom = '10px';
  202. clearCanvasButton.addEventListener('click', () => {
  203. let data = ["drawcmd", 0, [0.5, 0.5, 0.5, 0.5, !0, -2000, "#FFFFFF", -1, !1]];
  204. window.sockets.forEach(socket => {
  205. if (socket.readyState === WebSocket.OPEN) {
  206. socket.send(`42${JSON.stringify(data)}`);
  207. }
  208. });
  209. });
  210.  
  211. let joinButton = document.createElement('button');
  212. joinButton.textContent = 'Join';
  213. joinButton.style.padding = '10px';
  214. joinButton.style.borderRadius = '5px';
  215. joinButton.style.border = 'none';
  216. joinButton.style.background = 'linear-gradient(to bottom, white, #d3d3d3)';
  217. joinButton.style.color = '#003366';
  218. joinButton.style.cursor = 'pointer';
  219. joinButton.style.width = 'calc(100% - 20px)';
  220. joinButton.style.marginBottom = '10px';
  221. joinButton.addEventListener('mousedown', (e) => {
  222. window['___BOT'].room.join(EL('#invurl').value);
  223. });
  224.  
  225. let colorInput = document.createElement('input');
  226. colorInput.type = 'color';
  227. colorInput.value = '#000000';
  228. colorInput.style.margin = '10px 0';
  229.  
  230. innerContainer.appendChild(wordList);
  231. innerContainer.appendChild(fontSelect);
  232. innerContainer.appendChild(pixelSizeLabel);
  233. innerContainer.appendChild(pixelSizeSlider);
  234. innerContainer.appendChild(xPositionLabel);
  235. innerContainer.appendChild(xPositionSlider);
  236. innerContainer.appendChild(yPositionLabel);
  237. innerContainer.appendChild(yPositionSlider);
  238. innerContainer.appendChild(sendButton);
  239. innerContainer.appendChild(clearCanvasButton);
  240. innerContainer.appendChild(joinButton);
  241. innerContainer.appendChild(colorInput);
  242.  
  243. container.appendChild(innerContainer);
  244. document.body.appendChild(container);
  245.  
  246. // Make the container draggable
  247. let isDragging = false;
  248. let offsetX, offsetY;
  249.  
  250. container.addEventListener('mousedown', (e) => {
  251. if (e.target === container || e.target === title) {
  252. isDragging = true;
  253. offsetX = e.clientX - container.getBoundingClientRect().left;
  254. offsetY = e.clientY - container.getBoundingClientRect().top;
  255. container.style.cursor = 'grabbing';
  256. }
  257. });
  258.  
  259. document.addEventListener('mousemove', (e) => {
  260. if (isDragging) {
  261. container.style.left = `${e.clientX - offsetX}px`;
  262. container.style.top = `${e.clientY - offsetY}px`;
  263. }
  264. });
  265.  
  266. document.addEventListener('mouseup', () => {
  267. isDragging = false;
  268. container.style.cursor = 'move';
  269. });
  270. }
  271.  
  272. // Drawing Text on Canvas
  273. function drawTextOnCanvas(text, font, pixelSize, xPosition, yPosition) {
  274. let x = xPosition / 100; // Convert to percentage
  275. let y = yPosition / 100; // Convert to percentage
  276. let thickness = 5;
  277. let color = document.querySelector('input[type="color"]').value; // Get color from input
  278.  
  279. let canvas = document.createElement('canvas');
  280. let ctx = canvas.getContext('2d');
  281. canvas.width = 500;
  282. canvas.height = 100;
  283.  
  284. ctx.font = `${pixelSize}px ${font}`;
  285. ctx.fillStyle = color;
  286. ctx.fillText(text, 10, 50);
  287.  
  288. let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
  289. let commands = [];
  290.  
  291. for (let i = 0; i < imageData.length; i += 4) {
  292. if (imageData[i + 3] > 0) { // Alpha channel is not zero
  293. let px = (i / 4) % canvas.width;
  294. let py = Math.floor((i / 4) / canvas.width);
  295. let nx = x + (px / canvas.width);
  296. let ny = y + (py / canvas.height);
  297. commands.push([nx, ny, nx, ny, false, -thickness, color, 0, 0, {}]);
  298. }
  299. }
  300.  
  301. // Send commands in batches to avoid overloading the WebSocket
  302. const batchSize = 50;
  303. for (let i = 0; i < commands.length; i += batchSize) {
  304. let batch = commands.slice(i, i + batchSize);
  305. batch.forEach(cmd => {
  306. sendDrawCommand(cmd[0], cmd[1], cmd[2], cmd[3], thickness, color);
  307. });
  308. // Add a small delay to avoid overloading the WebSocket
  309. setTimeout(() => {}, 10);
  310. }
  311. }
  312.  
  313. // Sending Draw Command via WebSocket
  314. function sendDrawCommand(x1, y1, x2, y2, thickness, color) {
  315. let message = `42["drawcmd",0,[${x1},${y1},${x2},${y2},false,${0 - thickness},"${color}",0,0,{}]]`;
  316. window.sockets.forEach(socket => {
  317. if (socket.readyState === WebSocket.OPEN) {
  318. socket.send(message);
  319. }
  320. });
  321. }
  322.  
  323. // Overriding WebSocket send method to capture sockets
  324. const originalSend = WebSocket.prototype.send;
  325. WebSocket.prototype.send = function (...args) {
  326. if (window.sockets.indexOf(this) === -1) {
  327. window.sockets.push(this);
  328. }
  329. return originalSend.call(this, ...args);
  330. };
  331.  
  332. // Initializing
  333. window.sockets = [];
  334. addTextInput();
  335.  
  336. // Adding the bot functionality
  337. const EL = (sel) => document.querySelector(sel);
  338.  
  339. const Player = function (name = undefined) {
  340. this.name = name;
  341. this.sid1 = null;
  342. this.uid = '';
  343. this.wt = '';
  344. this.conn = new Connection(this);
  345. this.room = new Room(this.conn);
  346. this.action = new Actions(this.conn);
  347. };
  348.  
  349. Player.prototype.annonymize = function (name) {
  350. this.name = name;
  351. this.uid = undefined;
  352. this.wt = undefined;
  353. };
  354.  
  355. const Connection = function (player) {
  356. this.player = player;
  357. };
  358.  
  359. Connection.prototype.onopen = function (event) {
  360. this.Heartbeat(25000);
  361. };
  362.  
  363. Connection.prototype.onclose = function (event) {
  364. };
  365.  
  366. Connection.prototype.onerror = function (event) {
  367. };
  368.  
  369. Connection.prototype.onmessage = function (event) {
  370. let message = String(event.data);
  371. if (message.startsWith('42')) {
  372. this.onbroadcast(message.slice(2));
  373. } else if (message.startsWith('40')) {
  374. this.onrequest();
  375. } else if (message.startsWith('41')) {
  376. this.player.room.join(this.player.room.id);
  377. } else if (message.startsWith('430')) {
  378. let configs = JSON.parse(message.slice(3))[0];
  379. this.player.room.players = configs.players;
  380. this.player.room.id = configs.roomid;
  381. }
  382. };
  383.  
  384. Connection.prototype.onbroadcast = function (payload) {
  385. payload = JSON.parse(payload);
  386. if (payload[0] == 'bc_uc_freedrawsession_changedroom') {
  387. this.player.room.players = payload[3];
  388. this.player.room.id = payload[4];
  389. }
  390. if (payload[0] == 'mc_roomplayerschange') {
  391. this.player.room.players = payload[3];
  392. }
  393. };
  394.  
  395. Connection.prototype.onrequest = function () {};
  396.  
  397. Connection.prototype.open = function (url) {
  398. this.socket = new WebSocket(url);
  399. this.socket.onopen = this.onopen.bind(this);
  400. this.socket.onclose = this.onclose.bind(this);
  401. this.socket.onerror = this.onerror.bind(this);
  402. this.socket.onmessage = this.onmessage.bind(this);
  403. };
  404.  
  405. Connection.prototype.close = function (code, reason) {
  406. this.socket.close(code, reason);
  407. };
  408.  
  409. Connection.prototype.Heartbeat = function (interval) {
  410. let timeout = setTimeout(() => {
  411. if (this.socket.readyState == this.socket.OPEN) {
  412. this.socket.send(2);
  413. this.Heartbeat(interval);
  414. }
  415. }, interval);
  416. };
  417.  
  418. Connection.prototype.serverconnect = function (server, room) {
  419. if (this.socket == undefined || this.socket.readyState != this.socket.OPEN) {
  420. this.open(server);
  421. } else {
  422. this.socket.send(41);
  423. this.socket.send(40);
  424. }
  425. this.onrequest = () => {
  426. this.socket.send(room);
  427. };
  428. };
  429.  
  430. const Room = function (conn) {
  431. this.conn = conn;
  432. this.id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
  433. this.players = [];
  434. };
  435.  
  436. Room.prototype.join = function (invitelink) {
  437. let gamemode = 2;
  438. let server = '';
  439. if (invitelink == null) {
  440. this.id = null;
  441. server = 'sv3.';
  442. } else {
  443. this.id = invitelink.startsWith('http') ? invitelink.split('/').pop() : invitelink;
  444. if (invitelink.endsWith('.3')) {
  445. server = 'sv3.';
  446. gamemode = 2;
  447. } else if (invitelink.endsWith('.2')) {
  448. server = 'sv2.';
  449. gamemode = 2;
  450. } else {
  451. server = '';
  452. gamemode = 1;
  453. }
  454. }
  455. let serverurl = `wss://${server}drawaria.online/socket.io/?sid1=undefined&hostname=drawaria.online&EIO=3&transport=websocket`;
  456. let player = this.conn.player;
  457. let connectstring = `420["startplay","${player.name}",${gamemode},"en",${nullify(this.id)},null,[null,"https://drawaria.online/",1000,1000,[${nullify(player.sid1)},${nullify(player.uid)},${nullify(player.wt)}],null]]`;
  458. this.conn.serverconnect(serverurl, connectstring);
  459. };
  460.  
  461. Room.prototype.next = function () {
  462. if (this.conn.socket.readyState != this.conn.socket.OPEN) {
  463. this.join(null);
  464. } else {
  465. this.conn.socket.send('42["pgswtichroom"]');
  466. }
  467. };
  468.  
  469. const Actions = function (conn) {
  470. this.conn = conn;
  471. };
  472.  
  473. Actions.prototype.DrawLine = function (bx = 50, by = 50, ex = 50, ey = 50, thickness = 50, color = '#FFFFFF', algo = 0) {
  474. bx = bx / 100;
  475. by = by / 100;
  476. ex = ex / 100;
  477. ey = ey / 100;
  478. this.conn.socket.send(`42["drawcmd",0,[${bx},${by},${ex},${ey},true,${0 - thickness},"${color}",0,0,{"2":${algo},"3":0.5,"4":0.5}]]`);
  479. this.conn.socket.send(`42["drawcmd",0,[${bx},${by},${ex},${ey},false,${0 - thickness},"${color}",0,0,{"2":${algo},"3":0.5,"4":0.5}]]`);
  480. };
  481.  
  482. var nullify = (value = null) => {
  483. return value == null ? null : String().concat('"', value, '"');
  484. };
  485.  
  486. if (!document.getElementById('Engine-Cheatcontainer')) {
  487. window['___BOT'] = new Player('Text Writer');
  488. }
  489. })();