UNPKG

line-sticker-downloader

Version:

Tool that downloads stickers or emojis from the LINE store

112 lines (94 loc) 2.93 kB
const path = require("path"); const chalk = require("chalk"); const puppeteer = require("puppeteer"); const makeDir = require("make-dir"); const downloadImage = require("image-downloader").image; const ora = require("ora"); const apng2gif = require("apng2gif"); const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); function createContext(config) { const { url, dest = "stickers", animatedWaitDelay, convertToGif } = config; return { spinner: ora("Downloading stickers..."), config: { url, dest, animatedWaitDelay, convertToGif, }, }; } async function scrapeStickerUrls(context) { const { url: pageUrl, animatedWaitDelay } = context.config; const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(pageUrl); const stickerUrls = []; const elementHandles = await page.$$('ul > li [style^="background-image"]'); if (elementHandles.length === 0) { throw new Error("Could not find any stickers on the specified page"); } let index = 0; const total = elementHandles.length; for (const elementHandle of elementHandles) { index++; context.spinner.text = `Scraping stickers (${index}/${total})...`; await elementHandle.evaluate(node => node.click()); await sleep(animatedWaitDelay); const canvasHandles = await page.$$("canvas[data-apng-src]"); let url; if (canvasHandles.length === 2) { // First canvas is the product image; skip it url = await await page.evaluate( (el) => el.getAttribute("data-apng-src"), canvasHandles[1] ); } else { // Treat as non-animated sticker url = await page.evaluate( (el) => el.style.backgroundImage.replace(/^url\("|"\)/g, ""), elementHandle ); } stickerUrls.push(url); } browser.close(); return stickerUrls; } async function downloadStickers(config = {}) { let context; try { context = createContext(config); const { spinner, config: { dest, convertToGif }, } = context; spinner.start(); let urls = await scrapeStickerUrls(context); urls = Array.from(new Set(urls)); await makeDir(dest); context.spinner.text = `Downloading ${urls.length} stickers...`; await Promise.all( urls.map((url, i) => downloadImage({ url, dest: path.join(dest, `sticker-${i + 1}.png`), }) ) ); if (convertToGif) { context.spinner.text = `Converting ${urls.length} stickers to GIF...`; await Promise.all( urls.map((url, i) => apng2gif(path.join(dest, `sticker-${i + 1}.png`))) ); } spinner.succeed(chalk.green(`Saved stickers to ${dest}/`)); } catch (err) { if (context) { context.spinner.fail(chalk.red(err.message)); } console.error(err.stack); process.exit(1); } } module.exports = downloadStickers;