Guest User

AI Studio Anti-Censorship by SetW (VIBECODED)

a guest
Apr 4th, 2026
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.74 KB | None | 0 0
  1. // ==UserScript==
  2. // @name AI Studio Anti-Censorship by SetW (VIBECODED)
  3. // @namespace http://tampermonkey.net/
  4. // @version 7.0
  5. // @description Mobile optimized UI, numbered vault, dynamic buttons.
  6. // @match https://aistudio.google.com/*
  7. // @grant none
  8. // @icon https://ih1.redbubble.net/image.296402979.3147/st,small,507x507-pad,600x600,f8f8f8.u3.jpg
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. 'use strict';
  13.  
  14. let shieldedText = "";
  15. let tempBuffer = "";
  16. const STORAGE_KEY = "ai_studio_vault";
  17. let currentViewId = null;
  18.  
  19. // Paleta de colores nueva
  20. const COLORS = {
  21. bg0: '#050505', // Fondo ultra oscuro (modal overlay)
  22. bg1: '#101010', // Fondo principal (modal content)
  23. bg2: '#1a1a1a', // Fondo secundario (sidebar, cards)
  24. border: '#2a2a2a', // Bordes sutiles
  25. accent: '#90D5FF', // Verde Matrix brillante (bordes activos, títulos)
  26. textMain: '#e0e0e0', // Texto principal
  27. textMuted: '#888888', // Texto secundario
  28. btnRescue: '#333333', // Fondo botón flotante (verde muy oscuro)
  29. btnRescueText: '#90D5FF', // Texto botón flotante
  30. btnCopy: '#4CAF50', // Verde estándar para copiar
  31. btnSave: '#008CBA', // Azul estándar para guardar (lo mantenemos para diferenciar)
  32. btnDel: '#d9534f', // Rojo estándar para borrar (lo mantenemos por seguridad visual)
  33. btnDef: '#333333' // Botón gris por defecto (Close, Vault inactivo)
  34. };
  35.  
  36. const getSavedTexts = () => JSON.parse(localStorage.getItem(STORAGE_KEY) || "[]");
  37.  
  38. const saveTextToVault = (text) => {
  39. const saved = getSavedTexts();
  40. saved.push({ id: Date.now(), text: text });
  41. localStorage.setItem(STORAGE_KEY, JSON.stringify(saved));
  42. renderSidebar();
  43. };
  44.  
  45. const deleteTextFromVault = (id) => {
  46. let saved = getSavedTexts();
  47. saved = saved.filter(item => item.id !== id);
  48. localStorage.setItem(STORAGE_KEY, JSON.stringify(saved));
  49. renderSidebar();
  50. };
  51.  
  52. // --- BOTÓN ARRASTRABLE ---
  53. const rescueBtn = document.createElement('button');
  54. rescueBtn.innerText = "🚨 Rescue Text";
  55. // Aplicando nuevos colores
  56. rescueBtn.style.cssText = `position:fixed;bottom:20px;right:20px;z-index:99999;background:${COLORS.btnRescue};color:${COLORS.btnRescueText};border:1px solid ${COLORS.accent};border-radius:8px;padding:12px 20px;font-family:monospace;font-size:14px;font-weight:bold;cursor:pointer;box-shadow:0 0 10px rgba(0,255,65,0.3);transition:transform 0.2s, box-shadow 0.2s;touch-action:none;`;
  57. document.body.appendChild(rescueBtn);
  58.  
  59. let isDragging = false, dragStartX, dragStartY, moved = false;
  60.  
  61. const dragStart = (e) => {
  62. moved = false;
  63. const clientX = e.type.includes('mouse') ? e.clientX : e.touches[0].clientX;
  64. const clientY = e.type.includes('mouse') ? e.clientY : e.touches[0].clientY;
  65. dragStartX = clientX - rescueBtn.getBoundingClientRect().left;
  66. dragStartY = clientY - rescueBtn.getBoundingClientRect().top;
  67. rescueBtn.style.bottom = 'auto';
  68. rescueBtn.style.right = 'auto';
  69. rescueBtn.style.transition = 'none';
  70. if (e.type.includes('mouse')) {
  71. document.addEventListener('mousemove', drag);
  72. document.addEventListener('mouseup', dragEnd);
  73. } else {
  74. document.addEventListener('touchmove', drag, { passive: false });
  75. document.addEventListener('touchend', dragEnd);
  76. }
  77. };
  78.  
  79. const drag = (e) => {
  80. moved = true; isDragging = true;
  81. e.preventDefault();
  82. const clientX = e.type.includes('mouse') ? e.clientX : e.touches[0].clientX;
  83. const clientY = e.type.includes('mouse') ? e.clientY : e.touches[0].clientY;
  84. rescueBtn.style.left = (clientX - dragStartX) + 'px';
  85. rescueBtn.style.top = (clientY - dragStartY) + 'px';
  86. rescueBtn.style.boxShadow = `0 0 20px ${COLORS.accent}`; // Brillo extra al mover
  87. };
  88.  
  89. const dragEnd = (e) => {
  90. rescueBtn.style.transition = 'transform 0.2s, box-shadow 0.2s';
  91. rescueBtn.style.boxShadow = `0 0 10px rgba(0,255,65,0.3)`;
  92. setTimeout(() => { isDragging = false; }, 50);
  93. if (e.type.includes('mouse')) {
  94. document.removeEventListener('mousemove', drag);
  95. document.removeEventListener('mouseup', dragEnd);
  96. } else {
  97. document.removeEventListener('touchmove', drag);
  98. document.removeEventListener('touchend', dragEnd);
  99. }
  100. };
  101.  
  102. rescueBtn.addEventListener('mousedown', dragStart);
  103. rescueBtn.addEventListener('touchstart', dragStart, { passive: false });
  104. rescueBtn.addEventListener('mouseover', () => { if(!isDragging) rescueBtn.style.transform = "scale(1.05)"; });
  105. rescueBtn.addEventListener('mouseout', () => rescueBtn.style.transform = "scale(1)");
  106.  
  107. // --- MODAL Y UI (Colores actualizados) ---
  108. const modal = document.createElement('div');
  109. // Fondo overlay negro casi puro
  110. modal.style.cssText = `display:none;position:fixed;top:0;left:0;width:100vw;height:100vh;background:${COLORS.bg0}da;z-index:100000;justify-content:center;align-items:center;`;
  111.  
  112. const modalContent = document.createElement('div');
  113. // Fondo principal negro, borde verde Matrix
  114. modalContent.style.cssText = `background:${COLORS.bg1};width:95%;max-width:1100px;height:85vh;border-radius:12px;border:2px solid ${COLORS.accent};display:flex;flex-direction:row;box-shadow:0 0 30px rgba(0,255,65,0.2);overflow:hidden;`;
  115.  
  116. const mainPanel = document.createElement('div');
  117. mainPanel.style.cssText = `flex:1;min-width:0;padding:15px;display:flex;flex-direction:column;border-right:1px solid ${COLORS.border};`;
  118.  
  119. const title = document.createElement('h3');
  120. title.innerText = "Recovered Text";
  121. // Título en verde Matrix
  122. title.style.cssText = `color:${COLORS.accent};margin-top:0;margin-bottom:10px;font-family:monospace;font-size:16px;text-transform:uppercase;letter-spacing:1px;`;
  123.  
  124. const textArea = document.createElement('textarea');
  125. // Fondo negro puro para el texto, texto gris claro
  126. textArea.style.cssText = `flex-grow:1;background:#000000;color:${COLORS.textMain};border:1px solid ${COLORS.border};border-radius:6px;padding:15px;font-family:monospace;font-size:14px;resize:none;outline:none;margin-bottom:15px;width:100%;box-sizing:border-box;line-height:1.5;`;
  127. textArea.readOnly = true;
  128.  
  129. const buttonRow = document.createElement('div');
  130. buttonRow.style.cssText = `display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap;`;
  131.  
  132. const copyBtn = document.createElement('button');
  133. copyBtn.innerText = "📋 Copy";
  134. copyBtn.style.cssText = `background:${COLORS.btnCopy};color:#fff;border:none;border-radius:6px;padding:10px;cursor:pointer;font-weight:bold;transition:0.2s;flex-grow:1;max-width:100px;font-family:sans-serif;`;
  135. copyBtn.addEventListener('click', () => {
  136. navigator.clipboard.writeText(textArea.value);
  137. copyBtn.innerText = "✅ Copied!";
  138. copyBtn.style.background = "#3d8b40";
  139. setTimeout(() => { copyBtn.innerText = "📋 Copy"; copyBtn.style.background = COLORS.btnCopy; }, 2000);
  140. });
  141.  
  142. const saveBtn = document.createElement('button');
  143. saveBtn.innerText = "💾 Save";
  144. saveBtn.style.cssText = `background:${COLORS.btnSave};color:#fff;border:none;border-radius:6px;padding:10px;cursor:pointer;font-weight:bold;transition:0.2s;flex-grow:1;max-width:100px;font-family:sans-serif;`;
  145. saveBtn.addEventListener('click', () => {
  146. if(textArea.value && !textArea.value.includes("Vault is empty")) {
  147. saveTextToVault(textArea.value);
  148. saveBtn.innerText = "✅ Saved!";
  149. saveBtn.style.background = "#006f94";
  150. setTimeout(() => { saveBtn.innerText = "💾 Save"; saveBtn.style.background = COLORS.btnSave; }, 2000);
  151. }
  152. });
  153.  
  154. const deleteBtn = document.createElement('button');
  155. deleteBtn.innerText = "🗑️ Delete";
  156. deleteBtn.style.cssText = `background:${COLORS.btnDel};color:#fff;border:none;border-radius:6px;padding:10px;cursor:pointer;font-weight:bold;transition:0.2s;flex-grow:1;max-width:100px;display:none;font-family:sans-serif;`;
  157. deleteBtn.addEventListener('click', () => {
  158. if (currentViewId) {
  159. deleteTextFromVault(currentViewId);
  160. currentViewId = null;
  161. textArea.value = shieldedText || "Vault is empty. The filter attacked before anything was generated.";
  162. title.innerText = "Recovered Text";
  163. updateActionButtons();
  164. }
  165. });
  166.  
  167. const closeBtn = document.createElement('button');
  168. closeBtn.innerText = "Close";
  169. closeBtn.style.cssText = `background:${COLORS.btnDef};color:${COLORS.textMain};border:none;border-radius:6px;padding:10px;cursor:pointer;font-weight:bold;flex-grow:1;max-width:100px;font-family:sans-serif;`;
  170. closeBtn.addEventListener('click', () => modal.style.display = "none");
  171.  
  172. const updateActionButtons = () => {
  173. if (currentViewId) {
  174. saveBtn.style.display = "none";
  175. deleteBtn.style.display = "block";
  176. } else {
  177. saveBtn.style.display = "block";
  178. deleteBtn.style.display = "none";
  179. }
  180. };
  181.  
  182. buttonRow.appendChild(copyBtn);
  183. buttonRow.appendChild(saveBtn);
  184. buttonRow.appendChild(deleteBtn);
  185. buttonRow.appendChild(closeBtn);
  186.  
  187. mainPanel.appendChild(title);
  188. mainPanel.appendChild(textArea);
  189. mainPanel.appendChild(buttonRow);
  190.  
  191. const sidebar = document.createElement('div');
  192. // Fondo negro ligeramente más claro que el principal
  193. sidebar.style.cssText = `width:60px;padding:15px 5px;display:flex;flex-direction:column;background:${COLORS.bg2};overflow-y:auto;align-items:center;flex-shrink:0;`;
  194.  
  195. const savedList = document.createElement('div');
  196. savedList.style.cssText = `display:flex;flex-direction:column;gap:15px;width:100%;align-items:center;`;
  197. sidebar.appendChild(savedList);
  198.  
  199. const renderSidebar = () => {
  200. savedList.replaceChildren();
  201. const items = getSavedTexts();
  202.  
  203. const btnMain = document.createElement('button');
  204. btnMain.innerText = "🚨";
  205. btnMain.title = "Current Rescue";
  206. // Si está seleccionado, brilla en verde. Si no, borde gris oscuro.
  207. btnMain.style.cssText = `width:40px;height:40px;border-radius:50%;background:${COLORS.bg1};color:#fff;border:1px solid ${currentViewId === null ? COLORS.accent : COLORS.border};box-shadow: ${currentViewId === null ? `0 0 10px ${COLORS.accent}` : 'none'};font-weight:bold;cursor:pointer;transition:0.2s;display:flex;justify-content:center;align-items:center;`;
  208. btnMain.addEventListener('click', () => {
  209. currentViewId = null;
  210. textArea.value = shieldedText || "Vault is empty. The filter attacked before anything was generated.";
  211. title.innerText = "Recovered Text";
  212. updateActionButtons();
  213. renderSidebar();
  214. });
  215. savedList.appendChild(btnMain);
  216.  
  217. const divider = document.createElement('div');
  218. divider.style.cssText = `width:30px;height:1px;background:${COLORS.border};margin:5px 0;`;
  219. savedList.appendChild(divider);
  220.  
  221. items.forEach((item, index) => {
  222. const btn = document.createElement('button');
  223. const isSelected = currentViewId === item.id;
  224. btn.innerText = index + 1;
  225. // Números en grismuted, seleccionados brillan en verde.
  226. btn.style.cssText = `width:40px;height:40px;border-radius:50%;background:${COLORS.bg1};color:${isSelected ? COLORS.accent : COLORS.textMuted};border:1px solid ${isSelected ? COLORS.accent : COLORS.border}; box-shadow: ${isSelected ? `0 0 10px ${COLORS.accent}` : 'none'}; font-weight:bold;cursor:pointer;transition:0.2s;display:flex;justify-content:center;align-items:center;font-size:16px;font-family:monospace;`;
  227.  
  228. btn.addEventListener('click', () => {
  229. currentViewId = item.id;
  230. textArea.value = item.text;
  231. title.innerText = `Vault Text #${index + 1}`;
  232. updateActionButtons();
  233. renderSidebar();
  234. });
  235. savedList.appendChild(btn);
  236. });
  237. };
  238.  
  239. modalContent.appendChild(mainPanel);
  240. modalContent.appendChild(sidebar);
  241. modal.appendChild(modalContent);
  242. document.body.appendChild(modal);
  243.  
  244. rescueBtn.addEventListener('click', (e) => {
  245. if (moved || isDragging) { e.preventDefault(); return; }
  246.  
  247. currentViewId = null;
  248. title.innerText = "Recovered Text";
  249. if (shieldedText.trim() === "") {
  250. textArea.value = "Vault is empty. The filter attacked before anything was generated.";
  251. } else {
  252. textArea.value = shieldedText;
  253. }
  254. updateActionButtons();
  255. renderSidebar();
  256. modal.style.display = "flex";
  257. });
  258.  
  259. const observer = new MutationObserver(() => {
  260. const containers = document.querySelectorAll('.model-prompt-container');
  261. if (containers.length === 0) return;
  262.  
  263. const lastContainer = containers[containers.length - 1];
  264. const currentText = lastContainer.innerText || lastContainer.textContent || "";
  265.  
  266. if (currentText.includes("Content blocked") || currentText.includes("warning")) return;
  267.  
  268. if (currentText.length > tempBuffer.length) {
  269. tempBuffer = currentText;
  270. shieldedText = currentText;
  271. } else if (currentText.length < tempBuffer.length) {
  272. tempBuffer = currentText;
  273. }
  274. });
  275.  
  276. observer.observe(document.body, { childList: true, subtree: true, characterData: CHARACTER_DATA });
  277.  
  278. })();
Advertisement
Add Comment
Please, Sign In to add comment