UNPKG

twdl

Version:

Downloads image and video tweets from Twitter

120 lines 4.04 kB
import { Readable } from 'node:stream'; import LruCache from 'lru-cache'; import _debug from 'debug'; import fs from 'fs/promises'; import { tmpdir } from 'node:os'; import path from 'node:path'; const debug = _debug('twdl:cache'); const lruCache = new LruCache({ max: parseInt(process.env.TWDL_CACHE_MAX, 10) || 500, ttl: parseInt(process.env.TWDL_CACHE_TTL, 10) || (1000 * 60 * 60), }); export function writeCache(response, twdlOptions) { twdlOptions = twdlOptions || global.argv; if (twdlOptions?.cache) { const cacheName = getCacheName(response.request.options); if (!lruCache.has(cacheName) && cacheName) { if (response.statusCode === 200 && response.body) { debug("Writing cache for '%s' to '%s'", response.url, cacheName); lruCache.set(cacheName, response.body); } } } return response; } export function readCache(requestOptions, twdlOptions) { twdlOptions = twdlOptions || global.argv; if (!twdlOptions?.cache) return; const cacheName = getCacheName(requestOptions), cachedData = lruCache.get(cacheName); if (cacheName && cachedData) { debug("Reading cache for '%s' from '%s'", requestOptions.url.toString(), cacheName); const response = new Readable({ read() { this.push(cachedData); this.push(null); } }); response.statusCode = 200; response.headers = {}; response.socket = null; response.complete = true; return response; } } function getCachePath() { let cachePath = process.env.TWDL_CACHE_PATH; if (!cachePath) { cachePath = path.join(tmpdir(), '/twdl-cache.json'); } return cachePath; } export function dumpCache() { const cachePath = getCachePath(); debug("Saving cache to '%s'", cachePath); const dump = lruCache.dump(); return fs.writeFile(cachePath, JSON.stringify(dump), { encoding: 'utf8' }); } export function reloadCache(twdlOptions) { twdlOptions = twdlOptions || global.argv; if (!twdlOptions?.cache) { debug('Cache is not loaded because it is disabled.'); return Promise.resolve(); } const cachePath = getCachePath(); debug("Reloading cache from '%s'", cachePath); return fs.readFile(cachePath, 'utf8') .then(data => { try { const cache = JSON.parse(data); lruCache.load(cache); } catch (err) { debug("Failed to parse cache from '%s': %s", cachePath, err.toString()); } }, err => { if (err.code !== 'ENOENT') { debug("Failed to reload cache from '%s' (%s)", cachePath, err.toString()); } }); } export function getCacheName(options) { let url = options.url; if (typeof url === 'string') { url = new URL(url); } let match = url.href.match(/(nitter).*\/status\/([0-9]+)/i); if (match) { return `nitter-tweet-${match[2]}`; } match = url.href.match(/(nitter).*\/([a-z0-9_]+)/i); if (match) { return `nitter-user-${match[2]}`; } match = url.hostname.match(/savetweetvid/i); if (match) { const tweetUrl = decodeURIComponent(options.body); match = tweetUrl.match(/status\/([0-9]+)/i); if (match) { return `video-${match[1]}`; } } match = url.pathname.match(/find-twitter-id-answer/i); if (match) { const body = options.body; match = body.match(/username=([a-z0-9_]+)/i); if (match) { return `id-${match[1]}`; } } match = url.hostname.match(/tweeterid/i); if (match) { const body = options.body; match = body.match(/input=([a-z0-9_]+)/i); if (match) { return `id2-${match[1]}`; } } return false; } //# sourceMappingURL=cache.js.map