您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Downloads workflows from relay.app
// ==UserScript== // @name Relay.app Workflow Downloader // @namespace http://tampermonkey.net/ // @version 0.1 // @description Downloads workflows from relay.app // @author Jordan Haisley [email protected] // @match https://run.relay.app/workflows/*/edit // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // Add styles const style = document.createElement('style'); style.textContent = ` .download-workflow-btn { position: fixed; bottom: 20px; left: 20px; padding: 10px 20px; background: #0066cc; color: white; border: none; border-radius: 4px; cursor: pointer; z-index: 9999; } .download-workflow-btn:hover { background: #0052a3; } .download-workflow-btn.loading { background: #666; cursor: wait; } `; document.head.appendChild(style); // Save helper function saveJSON(data, filename) { if(!data) { console.error('No data'); return; } const jsonStr = typeof data === "object" ? JSON.stringify(data, undefined, 4) : data; const blob = new Blob([jsonStr], {type: 'text/json'}); const a = document.createElement('a'); a.download = filename; a.href = window.URL.createObjectURL(blob); a.click(); URL.revokeObjectURL(a.href); } // Get template ID from URL function getTemplateId() { const match = window.location.pathname.match(/\/workflows\/([^/]+)\/edit/); return match ? match[1] : null; } // Create minimal tRPC client const trpcClient = { query: async (path, input) => { const response = await fetch(`/api/trpc/${path}?input=${encodeURIComponent(JSON.stringify({json: input}))}`, { headers: { 'accept': 'application/json' }, credentials: 'include' }); if (!response.ok) { throw new Error('API request failed'); } const result = await response.json(); return result.result.data; } }; // Create and add button const button = document.createElement('button'); button.textContent = 'Download Workflow'; button.className = 'download-workflow-btn'; document.body.appendChild(button); // Add click handler button.addEventListener('click', async () => { button.textContent = 'Downloading...'; button.classList.add('loading'); try { const templateId = getTemplateId(); if (!templateId) { throw new Error('Could not find workflow ID'); } const result = await trpcClient.query('flowtemplate.load', { id: templateId }); saveJSON(result, `workflow_${templateId}.json`); } catch (error) { console.error('Download failed:', error); alert('Failed to download workflow'); } finally { button.textContent = 'Download Workflow'; button.classList.remove('loading'); } }); })();