|
|
@@ -12,14 +12,15 @@ interface IStreamConfig {
|
|
|
location: string;
|
|
|
url: string;
|
|
|
hashtags: string[];
|
|
|
+ screenshotSelector?: string;
|
|
|
+ clickSelector?: string;
|
|
|
+ screenshotDelay?: number;
|
|
|
}
|
|
|
|
|
|
export default class VideoStreams {
|
|
|
private readonly _name: string = "Video Streams";
|
|
|
private readonly _mastodonClient: mastodon.rest.Client;
|
|
|
private readonly _scraper: Scraper;
|
|
|
- private readonly _selector: string = "#mediaplaybackdiv_videoplayer";
|
|
|
- private readonly _clickSelector: string = config.VIDEO_STREAMS_CLICK_SELECTOR;
|
|
|
|
|
|
constructor(accessToken = config.MASTODON_TEST_ACCESS_TOKEN) {
|
|
|
accessToken = config.DEVELOP ? config.MASTODON_TEST_ACCESS_TOKEN : accessToken;
|
|
|
@@ -33,21 +34,26 @@ export default class VideoStreams {
|
|
|
return [];
|
|
|
}
|
|
|
|
|
|
- const streams: IStreamConfig[] = [];
|
|
|
- const streamPairs = streamsString.split(";");
|
|
|
-
|
|
|
- streamPairs.forEach((streamPair) => {
|
|
|
- const [location, url, hashTags] = streamPair.split("|");
|
|
|
- if (location && url) {
|
|
|
- streams.push({
|
|
|
- location: location.trim(),
|
|
|
- url: url.trim(),
|
|
|
- hashtags: hashTags?.split(",").map((h) => h.trim()).filter((h) => h !== "") ?? []
|
|
|
- });
|
|
|
+ try {
|
|
|
+ const parsed = JSON.parse(streamsString);
|
|
|
+ if (!Array.isArray(parsed)) {
|
|
|
+ throw new Error("VIDEO_STREAMS must be a JSON array");
|
|
|
}
|
|
|
- });
|
|
|
|
|
|
- return streams;
|
|
|
+ return parsed.map((item: any) => ({
|
|
|
+ location: String(item.location ?? "").trim(),
|
|
|
+ url: String(item.url ?? "").trim(),
|
|
|
+ hashtags: Array.isArray(item.hashtags)
|
|
|
+ ? item.hashtags.map((h: unknown) => String(h).trim()).filter((h: string) => h !== "")
|
|
|
+ : [],
|
|
|
+ screenshotSelector: item.screenshotSelector !== undefined ? String(item.screenshotSelector).trim() : undefined,
|
|
|
+ clickSelector: item.clickSelector !== undefined ? String(item.clickSelector).trim() : undefined,
|
|
|
+ screenshotDelay: item.screenshotDelay !== undefined ? Number(item.screenshotDelay) : undefined
|
|
|
+ })).filter((stream) => stream.location !== "" && stream.url !== "");
|
|
|
+ } catch (err: any) {
|
|
|
+ console.error(`${this._name} | Error parsing VIDEO_STREAMS: ${err.message}`);
|
|
|
+ throw err;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private base64ToFile(base64: string, fileName: string): File {
|
|
|
@@ -98,14 +104,22 @@ export default class VideoStreams {
|
|
|
for (const stream of streams) {
|
|
|
console.log(`${this._name} | Capturing ${stream.location}`);
|
|
|
|
|
|
- const response = await this._scraper.scrape({
|
|
|
+ const scrapeOptions: any = {
|
|
|
url: stream.url,
|
|
|
scraperMethod: ScraperMethods.PUPPETEER,
|
|
|
- screenshotSelector: this._selector,
|
|
|
- screenshotDelay: config.VIDEO_STREAMS_SCREENSHOT_DELAY,
|
|
|
- clickSelector: this._clickSelector,
|
|
|
- useProxy: true
|
|
|
- });
|
|
|
+ screenshotDelay: stream.screenshotDelay ?? config.VIDEO_STREAMS_SCREENSHOT_DELAY
|
|
|
+ };
|
|
|
+
|
|
|
+ if (stream.screenshotSelector !== undefined && stream.screenshotSelector !== "") {
|
|
|
+ scrapeOptions.screenshot = true;
|
|
|
+ scrapeOptions.screenshotSelector = stream.screenshotSelector;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (stream.clickSelector !== undefined && stream.clickSelector !== "") {
|
|
|
+ scrapeOptions.clickSelector = stream.clickSelector;
|
|
|
+ }
|
|
|
+
|
|
|
+ const response = await this._scraper.scrape(scrapeOptions);
|
|
|
|
|
|
const screenshotBase64 = response?.data?.data?.screenshot;
|
|
|
|