Skip to content

Instantly share code, notes, and snippets.

@zach-capalbo
Created May 16, 2020 14:28
Show Gist options
  • Save zach-capalbo/5d60d8b9c474a3d7284b985dfd0d9079 to your computer and use it in GitHub Desktop.
Save zach-capalbo/5d60d8b9c474a3d7284b985dfd0d9079 to your computer and use it in GitHub Desktop.
A Headless Mozilla Hubs Bot that drops easter eggs in a room
const ROOM_URL = "https://hub.link/cmPv8xv"
var HEADLESS_BROWSER = true
var puppeteer = require('puppeteer');
var browser
var page
async function launchBrowser () {
browser = await puppeteer.launch({headless: HEADLESS_BROWSER});
page = await browser.newPage();
const context = browser.defaultBrowserContext();
context.overridePermissions("https://hubs.mozilla.com", ['microphone', 'camera'])
context.overridePermissions("https://hubs.link", ['microphone', 'camera'])
await page.goto(ROOM_URL, {waitUntil: 'networkidle2'})
await page.waitFor("button")
if (HEADLESS_BROWSER) {
// Disable rendering for headless, otherwise chromium uses a LOT of CPU
await page.evaluate(() => { AFRAME.scenes[0].renderer.render = function() {} })
}
}
async function clickSelectorClassRegex(selector, classRegex) {
console.log(`Clicking for a ${selector} matching ${classRegex}`)
await page.evaluate((selector, classRegex) => {
classRegex = new RegExp(classRegex)
let buttons = Array.from(document.querySelectorAll(selector))
let enterButton = buttons.find(button => Array.from(button.classList).some(c => classRegex.test(c)))
enterButton.click()
}, selector, classRegex.toString().slice(1,-1))
}
async function enterRoom() {
await clickSelectorClassRegex("button", /entry__action/)
await page.waitFor("input")
await clickSelectorClassRegex("input", /profile__form-submit/)
await page.waitFor("button:nth-child(2)")
await clickSelectorClassRegex("button:nth-child(2)", /entry__entry-button/)
try {
await page.waitFor(2000)
await clickSelectorClassRegex("button", /mic-grant-panel__next/)
}
catch (e)
{
// Permission already granted
}
await page.waitFor(2000)
await clickSelectorClassRegex("button", /enter/)
}
async function addEasterEgg() {
await page.evaluate(async () => {
const eggURL = "https://uploads-prod.reticulum.io/files/031dca7b-2bcb-45b6-b2df-2371e71aecb1.glb"
let el = document.createElement("a-entity")
let loaded = new Promise((r, e) => { el.addEventListener('loaded', r, {once: true})})
el.setAttribute('scale', '1 1 1')
el.setAttribute('position', `${Math.random() * 3 - 1.5} ${Math.random() * 2 + 1} ${Math.random() * 4 - 2}`)
el.setAttribute('media-loader', {src: eggURL, resolve: true, fitToBox: true})
el.setAttribute('networked', {template: '#interactable-media'})
el.setAttribute("body-helper", { type: "dynamic", mass : 1 })
document.querySelector('a-scene').append(el)
await loaded
const DEFAULT_INTERACTABLE = 1 | 2 | 4 | 8
el.setAttribute("body-helper", { type: 'dynamic',
gravity: { x: Math.random() * 6 - 3, y: -9.8, z: Math.random() * 6 - 3 },
angularDamping: 0.01,
linearDamping: 0.01,
linearSleepingThreshold: 1.6,
angularSleepingThreshold: 2.5,
collisionFilterMask: DEFAULT_INTERACTABLE
});
})
}
async function runBot() {
try {
await launchBrowser()
await enterRoom()
setInterval(addEasterEgg, 5000)
} catch (e) {
page.screenshot({path: "botError.png"})
throw e
}
}
runBot()
@zach-capalbo
Copy link
Author

For folks finding this gist, consider using the new hubs-client-bot library instead: https://github.com/zach-capalbo/hubs-client-bot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment