Bumped to Node 24 and upgraded dependencies.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const config = require('config');
|
||||
const fetch = require('node-fetch');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const logger = require('../logger')(__filename);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const config = require('config');
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
async function eroshareAlbum(host) {
|
||||
const res = await fetch(`https://web.archive.org/web/20170630040157im_/https://eroshare.com/${host.id}`);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
async function eroshareItem(host, post) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const config = require('config');
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
const logger = require('../logger')(__filename);
|
||||
const { fetchPredata } = require('./imgurImage');
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const config = require('config');
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
async function fetchPredata() {
|
||||
const data = {
|
||||
|
||||
@@ -1,18 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
const mime = require('mime');
|
||||
const bhttp = require('bhttp');
|
||||
const { JSDOM } = require('jsdom');
|
||||
// reddit gallery images: `s.u` (still) or `s.gif`/`s.mp4` (animated) - URLs come back
|
||||
// HTML-entity-encoded (e.g. '&' instead of '&')
|
||||
function resolveMediaUrl(media) {
|
||||
const url = media?.s?.u || media?.s?.gif || media?.s?.mp4;
|
||||
|
||||
async function redditAlbum(host, post) {
|
||||
const res = await bhttp.get(host.url);
|
||||
return url ? url.replace(/&/g, '&') : null;
|
||||
}
|
||||
|
||||
if (res.statusCode !== 200) {
|
||||
throw new Error(res.body.toString());
|
||||
}
|
||||
async function redditAlbum(host, post, { reddit }) {
|
||||
// fetched through the authenticated/throttled client, not a raw fetch()/bhttp request -
|
||||
// reddit's anonymous-traffic bot challenge blocks plain unauthenticated .json requests
|
||||
const data = await reddit.getSubmission(post.id);
|
||||
|
||||
const { document } = new JSDOM(res.body.toString(), { runScripts: 'dangerously' }).window;
|
||||
const items = Array.from(document.querySelectorAll('li a'), el => el.href);
|
||||
const items = (data.gallery_data?.items || [])
|
||||
.filter((item) => !item.is_deleted)
|
||||
.map((item) => {
|
||||
const media = data.media_metadata?.[item.media_id];
|
||||
const url = resolveMediaUrl(media);
|
||||
|
||||
return url && {
|
||||
id: item.media_id,
|
||||
url,
|
||||
datetime: post.datetime,
|
||||
type: media.m || 'image/jpeg',
|
||||
};
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
return {
|
||||
album: {
|
||||
@@ -20,12 +34,7 @@ async function redditAlbum(host, post) {
|
||||
url: host.url,
|
||||
title: post.title,
|
||||
},
|
||||
items: items.map((url) => ({
|
||||
id: new URL(url).pathname.match(/\/(.*).\w+$/)?.[1],
|
||||
url,
|
||||
datetime: post.datetime,
|
||||
type: mime.getType(url) || 'image/jpeg',
|
||||
})),
|
||||
items,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
// the DASH manifest lists the actual audio track filename - reddit has changed this naming
|
||||
// scheme before (DASH_audio.mp4 -> /audio -> CMAF_AUDIO_128.mp4), so read it from the
|
||||
// manifest rather than guessing a hardcoded suffix off the video URL again
|
||||
function findAudioUrl(manifest, videoId) {
|
||||
const audioSection = manifest.match(/<AdaptationSet[^>]*contentType="audio"[^>]*>([\s\S]*?)<\/AdaptationSet>/);
|
||||
|
||||
async function redditVideo(host, post) {
|
||||
const res = await fetch(`${post.permalink}.json`);
|
||||
const [{ data }] = await res.json();
|
||||
if (!audioSection) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const videoUrl = data.children[0].data.media.reddit_video.fallback_url;
|
||||
const audioUrl = `${videoUrl.split('/').slice(0, -1).join('/')}/audio`;
|
||||
const baseUrls = [...audioSection[1].matchAll(/<BaseURL>([^<]+)<\/BaseURL>/g)].map((match) => match[1]);
|
||||
// representations are listed lowest to highest bandwidth - take the best one
|
||||
const audioFile = baseUrls[baseUrls.length - 1];
|
||||
|
||||
const audioRes = await fetch(audioUrl, {
|
||||
method: 'HEAD',
|
||||
});
|
||||
return audioFile ? `https://v.redd.it/${videoId}/${audioFile}` : null;
|
||||
}
|
||||
|
||||
async function findAudio(video, videoId) {
|
||||
if (!video.has_audio || !video.dash_url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const res = await fetch(video.dash_url);
|
||||
|
||||
if (!res.ok) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return findAudioUrl(await res.text(), videoId);
|
||||
}
|
||||
|
||||
async function redditVideo(host, post, { reddit }) {
|
||||
// fetched through the authenticated/throttled client, not a raw fetch() - reddit's
|
||||
// anonymous-traffic bot challenge blocks plain unauthenticated .json requests
|
||||
const data = await reddit.getSubmission(post.id);
|
||||
const video = data.media.reddit_video;
|
||||
const videoId = post.host.id || post.id;
|
||||
|
||||
const item = {
|
||||
album: null,
|
||||
items: [{
|
||||
id: post.host.id || post.id,
|
||||
url: videoUrl,
|
||||
id: videoId,
|
||||
url: video.fallback_url,
|
||||
title: post.title,
|
||||
datetime: post.datetime,
|
||||
type: 'video/mp4',
|
||||
@@ -25,7 +50,9 @@ async function redditVideo(host, post) {
|
||||
}],
|
||||
};
|
||||
|
||||
if (audioRes.status === 200) {
|
||||
const audioUrl = await findAudio(video, videoId);
|
||||
|
||||
if (audioUrl) {
|
||||
item.items[0].mux = [audioUrl];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
const mime = require('mime');
|
||||
// const unprint = require('unprint');
|
||||
|
||||
@@ -28,6 +27,11 @@ async function fetchPredata() {
|
||||
}
|
||||
|
||||
function scrapeGallery(data, { predata }) {
|
||||
if (!data.gifs.length) {
|
||||
// Math.min() of an empty array is Infinity, which becomes an invalid date below
|
||||
return null;
|
||||
}
|
||||
|
||||
const oldestDate = Math.min(...data.gifs.map((gif) => gif.createDate));
|
||||
|
||||
const curated = {
|
||||
|
||||
@@ -25,7 +25,7 @@ async function tube(host, post) {
|
||||
title: data.fulltitle || data.title,
|
||||
description: data.description,
|
||||
type: `video/${data.ext}`,
|
||||
datetime: dateFns.parse(data.upload_date, 'YYYYMMDD'),
|
||||
datetime: dateFns.parse(data.upload_date, 'yyyyMMdd', new Date()),
|
||||
original: data,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const config = require('config');
|
||||
const fetch = require('node-fetch');
|
||||
const UrlPattern = require('url-pattern');
|
||||
const cheerio = require('cheerio');
|
||||
const mime = require('mime-types');
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
const $ = require('cheerio');
|
||||
const mime = require('mime-types');
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
async function vidbleVideo(host, post) {
|
||||
|
||||
Reference in New Issue
Block a user