UNPKG

@acephale-green-party/coomer-downloader

Version:

Downloads images/videos from Coomer/Kemono/Reddit-NSFW user posts

61 lines (48 loc) 1.78 kB
import fetch from 'node-fetch'; import * as cheerio from 'cheerio'; import { testMediaType } from './../utils.js'; const userPostsURL = (n, user) => `https://nsfw.xxx/page/${n}?nsfw[]=0&types[]=image&types[]=video&types[]=gallery&slider=1&jsload=1&user=${user}&_=${Date.now()}`; async function getUserPosts(user) { console.log('Fetching user posts...'); const posts = []; for (let i = 1; i < 100000; i++) { const page = await fetch(userPostsURL(i, user)).then((r) => r.text()); if (page.length < 1) break; const $ = cheerio.load(page); const newPosts = $('a') .map((_, a) => $(a).attr('href')) .get() .filter((href) => href?.startsWith('https://nsfw.xxx/post')); posts.push(...newPosts); } return posts; } async function getPostsData(posts, mediaType) { console.log('Fetching posts data...'); const data = []; for (const post of posts) { const page = await fetch(post).then((r) => r.text()); const $ = cheerio.load(page); const src = $('.sh-section .sh-section__image img').attr('src') || $('.sh-section .sh-section__image video source').attr('src') || null; if (!src) continue; const slug = post.split('post/')[1].split('?')[0]; const date = $('.sh-section .sh-section__passed').first().text().replace(/ /g, '-') || ''; const ext = src.split('.').pop(); const name = `${slug}-${date}.${ext}`; data.push({ name, src }); } return data.filter((f) => testMediaType(f.name, mediaType)); } export async function getRedditData(url, mediaType) { const user = url.match(/u\/(\w+)/)[1]; const posts = await getUserPosts(user); const files = await getPostsData(posts, mediaType); const dirName = `${user}-reddit`; return { dirName, files }; }