46 lines
1.4 KiB
JavaScript
46 lines
1.4 KiB
JavaScript
import fs from 'node:fs';
|
|
import { chromium } from 'playwright';
|
|
import { ENABLE_POSTING, SESSION_FILE, USER_AGENT } from './common.js';
|
|
|
|
const text = process.argv.slice(2).join(' ').trim();
|
|
if (!text) {
|
|
console.error('Usage: npm run post -- "your post text"');
|
|
process.exit(1);
|
|
}
|
|
|
|
if (!ENABLE_POSTING) {
|
|
console.error('Posting is disabled. Set ENABLE_POSTING=true in .env to enable.');
|
|
process.exit(1);
|
|
}
|
|
|
|
if (!fs.existsSync(SESSION_FILE)) {
|
|
console.error('No session found. Run: npm run login');
|
|
process.exit(1);
|
|
}
|
|
|
|
const browser = await chromium.launch({ headless: true });
|
|
const context = await browser.newContext({
|
|
storageState: SESSION_FILE,
|
|
userAgent: USER_AGENT || undefined,
|
|
viewport: { width: 1366, height: 900 }
|
|
});
|
|
|
|
const page = await context.newPage();
|
|
await page.goto('https://x.com/compose/post', { waitUntil: 'domcontentloaded', timeout: 60000 });
|
|
await page.waitForSelector('[data-testid="tweetTextarea_0"]', { timeout: 20000 });
|
|
await page.fill('[data-testid="tweetTextarea_0"]', text);
|
|
|
|
// Safety: we require explicit --confirm to actually click Post
|
|
const confirmed = process.argv.includes('--confirm');
|
|
if (!confirmed) {
|
|
console.log('Draft prepared, not posted. Re-run with --confirm to publish.');
|
|
await browser.close();
|
|
process.exit(0);
|
|
}
|
|
|
|
await page.click('[data-testid="tweetButtonInline"]');
|
|
await page.waitForTimeout(2000);
|
|
|
|
console.log('Post submitted.');
|
|
await browser.close();
|