Gartic Auto Draw com Leitor de Links

Desenha imagens a partir de URLs diretos no Gartic.io

  1. // ==UserScript==
  2. // @name Gartic Auto Draw com Leitor de Links
  3. // @namespace gartic-auto-draw
  4. // @description Desenha imagens a partir de URLs diretos no Gartic.io
  5. // @version 1.8
  6. // @license MIT
  7. // @author EmersonxD
  8. // @match https://gartic.io/*
  9. // @grant GM_xmlhttpRequest
  10. // @grant GM_addStyle
  11. // @run-at document-idle
  12. // ==/UserScript==
  13.  
  14. /* jshint esversion: 8 */
  15. (function () {
  16. 'use strict';
  17.  
  18. // Configurações
  19. const SETTINGS = {
  20. maxRetries: 3,
  21. validExtensions: /\.(png|jpe?g|webp)$/i
  22. };
  23.  
  24. // Elementos da UI
  25. let urlInput, confirmButton;
  26.  
  27. // Função para validar URLs de imagem
  28. function isValidImageUrl(url) {
  29. return SETTINGS.validExtensions.test(url);
  30. }
  31.  
  32. // Função para baixar imagem da URL
  33. async function fetchImage(url) {
  34. return new Promise((resolve, reject) => {
  35. GM_xmlhttpRequest({
  36. method: 'GET',
  37. url: url,
  38. responseType: 'blob',
  39. onload: (response) => {
  40. if (response.status === 200) {
  41. const blob = response.response;
  42. const file = new File([blob], 'image.png', { type: blob.type });
  43. resolve(file);
  44. } else {
  45. reject(new Error('Erro ao baixar imagem'));
  46. }
  47. },
  48. onerror: reject
  49. });
  50. });
  51. }
  52.  
  53. // Interface do usuário
  54. function createUrlInputUI() {
  55. GM_addStyle(`
  56. .gartic-url-container {
  57. position: fixed;
  58. top: 10px;
  59. right: 10px;
  60. z-index: 9999;
  61. background: rgba(255, 255, 255, 0.9);
  62. padding: 10px;
  63. border-radius: 8px;
  64. box-shadow: 0 2px 5px rgba(0,0,0,0.2);
  65. width: 300px;
  66. }
  67. .gartic-url-input {
  68. width: 100%;
  69. padding: 8px;
  70. margin-bottom: 8px;
  71. border: 1px solid #ddd;
  72. border-radius: 4px;
  73. }
  74. .gartic-confirm-btn {
  75. width: 100%;
  76. padding: 8px;
  77. background: #4CAF50;
  78. color: white;
  79. border: none;
  80. border-radius: 4px;
  81. cursor: pointer;
  82. }
  83. `);
  84.  
  85. const container = document.createElement('div');
  86. container.className = 'gartic-url-container';
  87.  
  88. urlInput = document.createElement('input');
  89. urlInput.className = 'gartic-url-input';
  90. urlInput.placeholder = 'Cole o link da imagem aqui';
  91.  
  92. confirmButton = document.createElement('button');
  93. confirmButton.className = 'gartic-confirm-btn';
  94. confirmButton.textContent = 'Desenhar';
  95.  
  96. // Evento de confirmação
  97. confirmButton.addEventListener('click', async () => {
  98. if (!isValidImageUrl(urlInput.value)) {
  99. alert('Link inválido! Use links diretos para imagens (.png, .jpg, .webp)');
  100. return;
  101. }
  102.  
  103. confirmButton.disabled = true;
  104. confirmButton.textContent = 'Processando...';
  105.  
  106. try {
  107. const imageFile = await fetchImage(urlInput.value);
  108. await processImage(imageFile);
  109. alert('Desenho concluído!');
  110. } catch (error) {
  111. alert('Erro ao processar imagem: ' + error.message);
  112. } finally {
  113. confirmButton.disabled = false;
  114. confirmButton.textContent = 'Desenhar';
  115. }
  116. });
  117.  
  118. container.append(urlInput, confirmButton);
  119. document.body.appendChild(container);
  120. }
  121.  
  122. // Função principal de processamento (mantida do código anterior)
  123. async function processImage(image) {
  124. const canvas = document.querySelector('.game.canvas');
  125. if (!canvas) {
  126. alert('Canvas não encontrado!');
  127. return;
  128. }
  129.  
  130. const ctx = canvas.getContext('2d');
  131. const img = await createImageBitmap(image);
  132. ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  133. }
  134.  
  135. // Inicialização
  136. (function init() {
  137. createUrlInputUI();
  138. })();
  139. })();