Created
July 1, 2025 16:34
-
-
Save heyqbnk/3c3ae24b41d9d76c975058636e5a5c67 to your computer and use it in GitHub Desktop.
A small script to scrape all Telegram gifts using `getAvailableGifts` method and locally save their Lottie animations along with the first frame SVGs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import puppeteer from 'puppeteer'; | |
| export async function exportLottieToSvg(lottieJson) { | |
| const browser = await puppeteer.launch(); | |
| const page = await browser.newPage(); | |
| const frameNumber = 0; | |
| const width = 512; | |
| const height = 512; | |
| // Configure viewport. | |
| await page.setViewport({ width, height }); | |
| // Set the page content. | |
| await page.setContent(` | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.13.0/lottie.min.js"></script> | |
| <style> | |
| #animation { | |
| width: ${width}px; | |
| height: ${height}px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="animation"></div> | |
| <script> | |
| const animationData = ${JSON.stringify(lottieJson)}; | |
| const anim = lottie.loadAnimation({ | |
| container: document.getElementById('animation'), | |
| renderer: 'svg', // Force SVG renderer | |
| loop: false, | |
| autoplay: false, | |
| animationData: animationData | |
| }); | |
| // Jump to the target frame when loaded | |
| anim.addEventListener('DOMLoaded', () => { | |
| anim.goToAndStop(${frameNumber}, true); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |
| `); | |
| // Wait for the animation to render. | |
| await page.waitForFunction( | |
| (frame) => anim.currentFrame === frame, | |
| { polling: 100 }, | |
| frameNumber | |
| ); | |
| // Extract the SVG content. | |
| const svgContent = await page.evaluate(() => { | |
| const svgElement = document.querySelector('#animation svg'); | |
| return svgElement?.outerHTML || null; | |
| }); | |
| if (!svgContent) { | |
| throw new Error('SVG element not found!'); | |
| } | |
| await browser.close(); | |
| return svgContent; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import zlib from 'node:zlib'; | |
| import fs from 'node:fs'; | |
| import { resolve } from 'node:path'; | |
| import { optimize } from 'svgo'; | |
| import { exportLottieToSvg } from './exportLottieToSvg.mjs'; | |
| // Specify your Telegram Bot token and target directory here. | |
| const token = process.env.TOKEN; | |
| const targetDir = resolve(import.meta.dirname, './assets'); | |
| // Create the target directory. | |
| fs.mkdirSync(targetDir, { recursive: true }); | |
| // Calls the Telegram method. | |
| function call(method, body) { | |
| return fetch(`https://api.telegram.org/bot${token}/${method}`, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(body), | |
| }) | |
| .then(r => r.json()) | |
| .then(r => r.result); | |
| } | |
| const { gifts } = await call('getAvailableGifts'); | |
| for (const gift of gifts) { | |
| const { file_path: filePath } = await call('getFile', { file_id: gift.sticker.file_id }); | |
| const lottieJson = await fetch(`https://api.telegram.org/file/bot${token}/${filePath}`) | |
| .then(r => r.bytes()) | |
| .then(b => zlib.gunzipSync(b).toString('utf-8')) | |
| .then(JSON.parse); | |
| const svg = await exportLottieToSvg(lottieJson); | |
| const result = optimize(svg, { | |
| multipass: true, | |
| plugins: [ | |
| 'preset-default', | |
| 'removeDimensions', | |
| 'removeViewBox', | |
| 'removeXlink', | |
| ] | |
| }); | |
| fs.mkdirSync(resolve(targetDir, gift.id), { recursive: true }); | |
| fs.writeFileSync(resolve(targetDir, gift.id, 'image.svg'), result.data); | |
| fs.writeFileSync(resolve(targetDir, gift.id, 'lottie.json'), JSON.stringify(lottieJson)); | |
| console.log(`Processed ${gift.id}`); | |
| await new Promise(r => setTimeout(r, 200)); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "name": "abc", | |
| "version": "1.0.0", | |
| "description": "", | |
| "type": "module", | |
| "main": "index.js", | |
| "scripts": { | |
| "test": "echo \"Error: no test specified\" && exit 1" | |
| }, | |
| "keywords": [], | |
| "author": "", | |
| "license": "ISC", | |
| "packageManager": "[email protected]", | |
| "devDependencies": { | |
| "puppeteer": "^24.11.2", | |
| "svgo": "^4.0.0" | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Install required dependencies first. | |
| pnpm i puppeteer svgo | |
| # If needed, approve the puppeteer build. | |
| pnpm approve-builds | |
| # Run the script. | |
| TOKEN=YOUR_TELEGRAM_BOT_TOKEN node index.mjs |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment