How to use Puppeteer

First, you need to add "puppeteer" in config.capabilities of your template:

class Template implements OpenSubmitterTemplateProtocol {
  config: TemplateConfig = {
    // Based on this setting, OpenSubmitter will inject Puppeteer's page object into this template
    capabilities: ['puppeteer'],
    // other settings here
  }
  const page = null; // dummy property for your IDE
}

OpenSubmitter replaces page property in your template with Puppeteer's Page object. It does that by inheriting your template and overriding your template's properties. Just for your information, this is the exact code how it does that:

this.browser = await this.puppeteer.launch(this.getPuppeteerOptions());
this.page = await this.browser.newPage();
Full source code for reference is here.

Note that for launch option it uses result of getPuppeteerOptions function. This function checks if your template class has getPuppeteerArguments method and uses them if it does. If not, OpenSubmitter's default Puppeteer arguments are used. This method is useful if you want, for example, use a proxy:

getPuppeteerArguments(): string[] {
    return [
        '--proxy-server=123.45.12.34:8080'
    ]
}

If you do use a proxy and it requires authorization, don't forget to provide login and password before navigating:

await this.page.authenticate({
    username: "login",
    password: "password",
});

So right in the runTask method you may use Page object as you'd do in your usual Puppeteer script:

async runTask(task: TemplateTask) {

    // Navigate to a website:
    await this.page.goto("https://www.website.com/", {
    waitUntil: "networkidle0",
    timeout: 30000 //value in milliseconds
    });

    // Get focus to a text input and type in text there:
    const someInput = await this.page.$('#css-selector-here')
    await someInput.focus();
    await this.page.type('#css-selector-here', "my text")

    // Click on a link and wait for navigation to complete
    await Promise.all([
        this.page.click("a-link-css-here"),
        this.page.waitForNavigation({ waitUntil: 'networkidle0' }),
    ]);

    // Set a Recaptcha V2 token to its textarea
    await this.page.evaluate(async (recaptchaResponse) => {
            document.getElementsByName('g-captcha-response')[0].value = recaptchaResponse;
    }, recaptchaResponse);

    // Intercept requests and extract or manipulate headers:
    await this.page.setRequestInterception(true);
    this.page.on('request', (request) => {
        //abort to replace with out version of this file
        if (request.url().indexOf('some/address') !== -1) {

            // extracting headers
            const headers = request.headers();

            // adding new header
            headers['New-header'] = 'New header value';

            // continue with new header
            request.continue({ headers });

            // or abort the request at all
            request.abort();

        }
    })
}

Things you may want to do before navigating to a website:

async runTask(task: TemplateTask) {
    // Set an User-Agent
    await this.page.setUserAgent("----Custom user agent here----");

    // Remove webdriver flag
    await this.page.evaluateOnNewDocument(() => {
        delete navigator.__proto__.webdriver;
    });

    // Navigate
    // await this.page.goto("https://www.website.com/")

}

If you didn't find a Chromium page manipulation method here, just google it at Stackoverflow or use ChatGPT for help. A possible query to ChatGPT may look like this:

I'm writing a script in TypeScript which uses Puppeteer for browser automation. How do I [write your query here]?