174 lines
5.0 KiB
JavaScript
174 lines
5.0 KiB
JavaScript
// watches chaturbate for go live
|
|
|
|
import puppeteer from 'puppeteer-extra';
|
|
import { dirname } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
import StealthPlugin from 'puppeteer-extra-plugin-stealth'
|
|
import delay from 'delay'
|
|
import ReplPlugin from 'puppeteer-extra-plugin-repl'
|
|
import fsp from 'fs/promises';
|
|
import repl from 'puppeteer-extra-plugin-repl';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const browserDataDir = __dirname+'/futureporn-scout-datadir';
|
|
|
|
|
|
const searchInputSelector = 'body > app-root > div > div.site-wrapper.nav-bar-visible.nav-bar-top-visible > div > app-explore-route > div > app-account-explore-route > div > input'
|
|
const followButtonSelector = "xpath///app-account-follow-button/div/xd-localization-string[contains(., 'Follow')]"
|
|
const onlineIndicator = 'a.online-indicator.is-live'
|
|
|
|
// @todo Get this value from Strapi
|
|
const channels = [
|
|
'avabrooks'
|
|
]
|
|
|
|
|
|
const scrollDown = async (page) => {
|
|
console.log('scrolling down')
|
|
await page.keyboard.press('PageDown')
|
|
await page.evaluate(async () => {
|
|
window.scrollBy(0, 500);
|
|
});
|
|
}
|
|
|
|
const handleOnlineChannel = async (page) => {
|
|
const href = await page.evaluate(async () => {
|
|
const onlineIndicator = 'a.online-indicator.is-live'
|
|
const href = document.querySelector(onlineIndicator).href
|
|
return href
|
|
})
|
|
console.log(`${href} is online!`)
|
|
await fsp.appendFile('./data.csv', `${new Date().toISOString()},${href}\n`)
|
|
}
|
|
|
|
/**
|
|
* Open up a tab to the channel.
|
|
* Intercept websockets events which tell us when the channel is online
|
|
*/
|
|
const monitor = async (browser, channel) => {
|
|
if (!browser) throw new Error('monitor requires page arg');
|
|
if (!channel) throw new Error('monitor requires channel arg');
|
|
console.log(`monitoring ${channel}`)
|
|
const page = await browser.newPage();
|
|
|
|
await page.setRequestInterception(true);
|
|
|
|
const url = await new Promise((resolve) => {
|
|
page.on('request', interceptRequest => {
|
|
const url = interceptRequest.url();
|
|
console.log(url)
|
|
if (url.startsWith('wss://realtime')) {
|
|
console.log(`request! ${interceptRequest.url()} ${JSON.stringify(interceptRequest.headers(), null, 2)}`);
|
|
resolve(interceptRequest.url());
|
|
}
|
|
interceptRequest.continue();
|
|
});
|
|
|
|
page.goto(`https://chaturbate.com/${channel}`);
|
|
})
|
|
|
|
await page.repl()
|
|
}
|
|
|
|
const dash = async (page, channel) => {
|
|
console.log('check')
|
|
await page.goto(`https://chaturbate.com/${channel}`)
|
|
|
|
|
|
// look for is-live indicator
|
|
try {
|
|
console.log('waiting for home page')
|
|
await page.waitForSelector('div.stories-scroll-container', { timeout: 15000 })
|
|
console.log('waiting for online indicators')
|
|
await page.waitForSelector(onlineIndicator, { timeout: 10000 })
|
|
console.log(`FOUND online channel! ${JSON.stringify(onlineIndicator, null, 2)}`);
|
|
handleOnlineChannel(page)
|
|
delay(1000)
|
|
} catch (e) {
|
|
console.error(e)
|
|
console.log('error on the dash. lets move on.')
|
|
}
|
|
}
|
|
|
|
const discover = async (page) => {
|
|
|
|
// Navigate the page to a URL
|
|
await page.goto('https://fansly.com/explore/discover');
|
|
|
|
|
|
console.log('wait for search input')
|
|
await page.waitForSelector(searchInputSelector)
|
|
|
|
// console.log('click search input')
|
|
// await page.click(searchInputSelector)
|
|
|
|
console.log('type a random letter')
|
|
const letter = (() => {
|
|
const letters = 'abcdefghijklmnopqrstuvwxyz'
|
|
const randomIndex = Math.floor(Math.random() * letters.length);
|
|
return letters[randomIndex];
|
|
})()
|
|
await page.type(searchInputSelector, letter)
|
|
|
|
|
|
|
|
// // Start an interactive REPL here with the `page` instance.
|
|
// await page.repl()
|
|
// // Afterwards start REPL with the `browser` instance.
|
|
// await browser.repl()
|
|
|
|
let go = true
|
|
setTimeout(() => {
|
|
go = false
|
|
}, 1000*30*1) // ~2 minutes of following
|
|
|
|
while (go) {
|
|
try {
|
|
console.log('Wait for Follow/Unfollow buttons')
|
|
try {
|
|
await page.waitForSelector(followButtonSelector, { timeout: 1000 })
|
|
await page.click(followButtonSelector, { timeout: 1000 })
|
|
} catch {}
|
|
|
|
// look for is-live indicator
|
|
try {
|
|
await page.waitForSelector(onlineIndicator, { timeout: 100 })
|
|
console.log(`FOUND online channel! ${JSON.stringify(onlineIndicator, null, 2)}`);
|
|
handleOnlineChannel(page)
|
|
} catch (e) {
|
|
// console.log('online channel not found')
|
|
}
|
|
|
|
scrollDown(page)
|
|
await page.keyboard.press('PageDown')
|
|
} catch (e) {
|
|
console.error('Error while waiting for follow button')
|
|
console.error(e)
|
|
}
|
|
await delay(15000)
|
|
}
|
|
}
|
|
|
|
(async () => {
|
|
// Launch the browser and open a new blank page
|
|
puppeteer.use(StealthPlugin())
|
|
puppeteer.use(ReplPlugin())
|
|
const browser = await puppeteer.launch({
|
|
headless: false,
|
|
args: [
|
|
`--user-data-dir=${browserDataDir}`
|
|
]
|
|
});
|
|
|
|
|
|
for (const ch of channels) {
|
|
await monitor(browser, ch)
|
|
// await dash(page)
|
|
// await discover(page) // discover & follow
|
|
// await dash(page) // dashboard & see who's live
|
|
}
|
|
|
|
|
|
|
|
|
|
})(); |