whattocode-cli
Version:
CLI tool to get random project ideas from what-to-code.com
186 lines (157 loc) • 6.1 kB
JavaScript
const puppeteer = require('puppeteer-core');
const fs = require('fs');
const path = require('path');
const os = require('os');
const DATA_DIR = path.join(os.homedir(), '.whattocode');
const IDEAS_FILE = path.join(DATA_DIR, 'ideas.json');
function wordWrap(text, maxWidth) {
const words = text.split(' ');
const lines = [];
let currentLine = '';
words.forEach(word => {
if (currentLine.length + word.length + 1 <= maxWidth) {
currentLine = currentLine ? `${currentLine} ${word}` : word;
} else {
lines.push(currentLine);
currentLine = word;
}
});
if (currentLine) {
lines.push(currentLine);
}
return lines;
}
async function scrapeIdeas() {
console.log("Launching browser...");
const browser = await puppeteer.launch({ headless: "new" });
const page = await browser.newPage();
const ideas = [];
try {
console.log("Navigating to what-to-code.com...");
await page.goto("https://what-to-code.com", { waitUntil: 'networkidle0' });
console.log("Waiting for ideas to load...");
await page.waitForSelector(".Idea_idea__8CbUI");
console.log("Scrolling to load all ideas...");
let lastHeight = await page.evaluate('document.body.scrollHeight');
while (true) {
await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
await page.waitForTimeout(2000);
let newHeight = await page.evaluate('document.body.scrollHeight');
if (newHeight === lastHeight) {
break;
}
lastHeight = newHeight;
}
const cards = await page.$$(".Idea_idea__8CbUI");
console.log(`Found ${cards.length} ideas`);
for (let i = 0; i < cards.length; i++) {
try {
const title = await cards[i].$eval(".has-text-weight-bold", el => el.textContent);
const description = await cards[i].$eval(".subtitle", el => el.textContent);
const likes = await cards[i].$eval(".card-footer-item", el => el.textContent);
const idea = {
title: title.trim(),
description: description.trim(),
likes: parseInt(likes.split(" ")[0])
};
ideas.push(idea);
console.log(`Processed idea ${i + 1}/${cards.length}: ${title.trim()}`);
} catch (err) {
console.log(`Error processing card ${i + 1}:`, err.message);
}
}
} catch (err) {
console.error("Error during scraping:", err.message);
} finally {
await browser.close();
}
return ideas;
}
function loadIdeas() {
try {
if (fs.existsSync(IDEAS_FILE)) {
return JSON.parse(fs.readFileSync(IDEAS_FILE, 'utf8'));
}
} catch (err) {
console.error("Error loading ideas:", err.message);
}
return null;
}
function saveIdeas(ideas) {
try {
fs.mkdirSync(DATA_DIR, { recursive: true });
fs.writeFileSync(IDEAS_FILE, JSON.stringify(ideas, null, 2));
return true;
} catch (err) {
console.error("Error saving ideas:", err.message);
return false;
}
}
function getRandomIdea() {
const ideas = loadIdeas();
if (!ideas || ideas.length === 0) {
console.log("No ideas found. Please run 'whattocode update' first.");
return null;
}
return ideas[Math.floor(Math.random() * ideas.length)];
}
function printHelp() {
console.log(`
Usage: whattocode <command>
Commands:
random Get a random project idea
update Update the local database of ideas
help Show this help message
`);
}
async function main() {
const command = process.argv[2];
if (!command || command === 'help' || command === '-h' || command === '--help') {
printHelp();
return;
}
switch (command) {
case 'random':
const idea = getRandomIdea();
if (idea) {
const width = 70;
console.log("\n" + "=".repeat(width));
console.log(" Random Project Idea ".padStart((width + " Random Project Idea ".length) / 2, "=").padEnd(width, "="));
console.log("=".repeat(width) + "\n");
// box title
console.log("+" + "-".repeat(width - 2) + "+");
const titleLines = wordWrap(idea.title, width - 4);
titleLines.forEach(line => {
console.log(`| ${line.padEnd(width - 4)} |`);
});
console.log("+" + "-".repeat(width - 2) + "+\n");
// show description
console.log("Description:");
console.log("-".repeat(width));
const descLines = wordWrap(idea.description, width);
descLines.forEach(line => console.log(line));
// show amt. of likes
console.log("\n" + "-".repeat(width));
console.log(`[${idea.likes} likes]`.padStart(width));
console.log();
}
break;
case 'update':
console.log("Updating ideas database...");
const ideas = await scrapeIdeas();
if (ideas && ideas.length > 0) {
if (saveIdeas(ideas)) {
console.log(`Successfully saved ${ideas.length} ideas to ${IDEAS_FILE}`);
}
}
break;
default:
console.log(`Unknown command: ${command}`);
printHelp();
process.exit(1);
}
}
main().catch(err => {
console.error("Error:", err.message);
process.exit(1);
});