Grok Source File Uploader

Adds a button to upload any source files to Grok by renaming them to .txt so they are accepted.

当前为 2025-06-01 提交的版本,查看 最新版本

// ==UserScript==
// @name         Grok Source File Uploader
// @namespace    https://gf.qytechs.cn/users/your-username
// @version      1.1
// @description  Adds a button to upload any source files to Grok by renaming them to .txt so they are accepted.
// @author       Moore
// @match        *://x.com/i/grok*
// @match        *://*.x.com/i/grok*
// @grant        none
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

(function () {
  'use strict';

  function injectUploadButton() {
    const mediaBtn = document.querySelector('button[aria-label="Media"]');
    if (!mediaBtn || document.getElementById('custom-grok-upload-wrapper')) return;

    // Create wrapper div matching structure
    const wrapperDiv = document.createElement("div");
    wrapperDiv.className = mediaBtn.parentElement.className;
    wrapperDiv.id = "custom-grok-upload-wrapper";

    // Clone the original Media button
    const customBtn = mediaBtn.cloneNode(true);
    customBtn.id = "custom-grok-upload";
    customBtn.setAttribute("aria-label", "Upload source files");

    // Replace the SVG icon (styled like Grok's)
    customBtn.querySelector('svg').outerHTML = `
      <svg viewBox="0 0 24 24" aria-hidden="true"
           class="r-4qtqp9 r-yyyyoo r-dnmrzs r-bnwqim r-lrvibr r-m6rgpd r-1tl9yi8 r-1janqcz"
           style="color: rgb(182, 185, 188);">
        <g>
          <path d="M5 20h14v-2H5v2zm7-18L5.33 9h3.17v4h4.99v-4h3.17L12 2z"></path>
        </g>
      </svg>
    `;

    // Hidden file input for multi-upload
    const fileInput = document.createElement("input");
    fileInput.type = "file";
    fileInput.accept = "*.*";
    fileInput.multiple = true;
    fileInput.style.display = "none";

    customBtn.addEventListener("click", () => fileInput.click());

    fileInput.addEventListener("change", async (e) => {
      const files = Array.from(e.target.files);
      if (files.length === 0) return;

      const nativeInput = document.querySelector('input[type="file"]');
      if (!nativeInput) {
        alert("❌ Grok file input not found. Try clicking the 📎 icon manually first.");
        return;
      }

      const dt = new DataTransfer();
      for (const file of files) {
        const content = await file.text();
        const renamedFile = new File(
          [new Blob([content], { type: "text/plain" })],
          file.name.replace(/\.[^/.]+$/, "") + ".txt",
          { type: "text/plain" }
        );
        dt.items.add(renamedFile);
      }

      nativeInput.files = dt.files;
      nativeInput.dispatchEvent(new Event("change", { bubbles: true }));
      fileInput.value = "";
    });

    wrapperDiv.appendChild(customBtn);
    document.body.appendChild(fileInput);

    // Insert before the 📎 Media button's wrapper
    mediaBtn.parentElement.parentElement.insertBefore(wrapperDiv, mediaBtn.parentElement);
  }

  // Re-inject reliably on dynamic navigation
  const observer = new MutationObserver(() => {
    injectUploadButton();
  });

  observer.observe(document.body, {
    childList: true,
    subtree: true,
  });

  // One initial manual inject
  setTimeout(injectUploadButton, 1000);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址