Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Post articles and image-text content to WeChat Official Account via API or Chrome CDP, with markdown-to-WeChat HTML conversion.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/paste-from-clipboard.ts
1import { spawnSync } from 'node:child_process';2import process from 'node:process';34function printUsage(exitCode = 0): never {5console.log(`Send real paste keystroke (Cmd+V / Ctrl+V) to the frontmost application67This bypasses CDP's synthetic events which websites can detect and ignore.89Usage:10npx -y bun paste-from-clipboard.ts [options]1112Options:13--retries <n> Number of retry attempts (default: 3)14--delay <ms> Delay between retries in ms (default: 500)15--app <name> Target application to activate first (macOS only)16--help Show this help1718Examples:19# Simple paste20npx -y bun paste-from-clipboard.ts2122# Paste to Chrome with retries23npx -y bun paste-from-clipboard.ts --app "Google Chrome" --retries 52425# Quick paste with shorter delay26npx -y bun paste-from-clipboard.ts --delay 20027`);28process.exit(exitCode);29}3031function sleepSync(ms: number): void {32Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);33}3435function activateApp(appName: string): boolean {36if (process.platform !== 'darwin') return false;3738// Activate and wait for app to be frontmost39const script = `40tell application "${appName}"41activate42delay 0.543end tell4445-- Verify app is frontmost46tell application "System Events"47set frontApp to name of first application process whose frontmost is true48if frontApp is not "${appName}" then49tell application "${appName}" to activate50delay 0.351end if52end tell53`;54const result = spawnSync('osascript', ['-e', script], { stdio: 'pipe' });55return result.status === 0;56}5758function pasteMac(retries: number, delayMs: number, targetApp?: string): boolean {59for (let i = 0; i < retries; i++) {60// Build script that activates app (if specified) and sends keystroke in one atomic operation61const script = targetApp62? `63tell application "${targetApp}"64activate65end tell66delay 0.367tell application "System Events"68keystroke "v" using command down69end tell70`71: `72tell application "System Events"73keystroke "v" using command down74end tell75`;7677const result = spawnSync('osascript', ['-e', script], { stdio: 'pipe' });78if (result.status === 0) {79return true;80}8182const stderr = result.stderr?.toString().trim();83if (stderr) {84console.error(`[paste] osascript error: ${stderr}`);85}8687if (i < retries - 1) {88console.error(`[paste] Attempt ${i + 1}/${retries} failed, retrying in ${delayMs}ms...`);89sleepSync(delayMs);90}91}92return false;93}9495function pasteLinux(retries: number, delayMs: number): boolean {96// Try xdotool first (X11), then ydotool (Wayland)97const tools = [98{ cmd: 'xdotool', args: ['key', 'ctrl+v'] },99{ cmd: 'ydotool', args: ['key', '29:1', '47:1', '47:0', '29:0'] }, // Ctrl down, V down, V up, Ctrl up100];101102for (const tool of tools) {103const which = spawnSync('which', [tool.cmd], { stdio: 'pipe' });104if (which.status !== 0) continue;105106for (let i = 0; i < retries; i++) {107const result = spawnSync(tool.cmd, tool.args, { stdio: 'pipe' });108if (result.status === 0) {109return true;110}111if (i < retries - 1) {112console.error(`[paste] Attempt ${i + 1}/${retries} failed, retrying in ${delayMs}ms...`);113sleepSync(delayMs);114}115}116return false;117}118119console.error('[paste] No supported tool found. Install xdotool (X11) or ydotool (Wayland).');120return false;121}122123function pasteWindows(retries: number, delayMs: number): boolean {124const ps = `125Add-Type -AssemblyName System.Windows.Forms126[System.Windows.Forms.SendKeys]::SendWait("^v")127`;128129for (let i = 0; i < retries; i++) {130const result = spawnSync('powershell.exe', ['-NoProfile', '-Command', ps], { stdio: 'pipe' });131if (result.status === 0) {132return true;133}134if (i < retries - 1) {135console.error(`[paste] Attempt ${i + 1}/${retries} failed, retrying in ${delayMs}ms...`);136sleepSync(delayMs);137}138}139return false;140}141142function paste(retries: number, delayMs: number, targetApp?: string): boolean {143switch (process.platform) {144case 'darwin':145return pasteMac(retries, delayMs, targetApp);146case 'linux':147return pasteLinux(retries, delayMs);148case 'win32':149return pasteWindows(retries, delayMs);150default:151console.error(`[paste] Unsupported platform: ${process.platform}`);152return false;153}154}155156async function main(): Promise<void> {157const args = process.argv.slice(2);158159let retries = 3;160let delayMs = 500;161let targetApp: string | undefined;162163for (let i = 0; i < args.length; i++) {164const arg = args[i] ?? '';165if (arg === '--help' || arg === '-h') {166printUsage(0);167}168if (arg === '--retries' && args[i + 1]) {169retries = parseInt(args[++i]!, 10) || 3;170} else if (arg === '--delay' && args[i + 1]) {171delayMs = parseInt(args[++i]!, 10) || 500;172} else if (arg === '--app' && args[i + 1]) {173targetApp = args[++i];174} else if (arg.startsWith('-')) {175console.error(`Unknown option: ${arg}`);176printUsage(1);177}178}179180if (targetApp) {181console.log(`[paste] Target app: ${targetApp}`);182}183console.log(`[paste] Sending paste keystroke (retries=${retries}, delay=${delayMs}ms)...`);184const success = paste(retries, delayMs, targetApp);185186if (success) {187console.log('[paste] Paste keystroke sent successfully');188} else {189console.error('[paste] Failed to send paste keystroke');190process.exit(1);191}192}193194await main();195