reddit | reddit login | test reddit post | Search

The redditPost function automates posting on Reddit using Selenium WebDriver, taking parameters such as content, start page, and driver instance to create and submit a post. It handles errors and uses Markdown formatting for the title and body, with optional title generation using a Large Language Model.

Run example

npm run import -- "reddit post"

reddit post

const loginReddit = importer.import("reddit login")
const getClient = importer.import("selenium client")
const getAllQuery = importer.import("selenium query")
const { By } = require('selenium-webdriver')


async function redditPost(driver, content, startPage) {
  let {llmPrompt} = await importer.import("create llm session")

  if(!startPage.includes('://')) {
    startPage = 'https://www.reddit.com/r/' + startPage
  }

  if(!startPage.includes('/submit')) {
    startPage += '/submit?type=TEXT'
  }

  if(!driver) {
    driver = await getClient()
  }

  await driver.get(startPage)

  await loginReddit(driver)

  await new Promise(resolve => setTimeout(resolve, 1500))

  let titleStr = (/\*\*(.*?)\*\*\n*/gi).exec(content)
  if(titleStr) {
    content = content.replace(titleStr[0], '')
    titleStr = titleStr[1].replaceAll(/[#*"']/gi, '')
  } else {
    titleStr = await llmPrompt(
      'Generate a short title for this summary:\n' + 
      content)
    titleStr = titleStr.replaceAll(/[#*"']/gi, '')
  }

  try {
    let title = await driver.findElement(By.css('faceplate-textarea-input[name*="title"]'))
    await title.click()
    //await driver.executeScript('arguments[0].click();', title)
    await driver.actions().sendKeys(titleStr).perform()

    let switchButton = await getAllQuery(driver, [
      'shreddit-composer',
      'button[aria-label*="Switch to Markdown"]'
    ])
    await driver.executeScript('arguments[0].click();', switchButton[0])
    await new Promise(resolve => setTimeout(resolve, 500))

    let body = await getAllQuery(driver, [
      'shreddit-composer',
      'shreddit-markdown-composer',
      'textarea[placeholder*="Body"]'
    ])
    await driver.executeScript('arguments[0].click();', body[0])
    await driver.actions().sendKeys(content).perform()

    let submit = await driver.findElement(By.css('#submit-post-button'))
    submit.click()
    await new Promise(resolve => setTimeout(resolve, 1500))

  } catch (e) {
    //driver.quit()

    throw e
  }

}

module.exports = redditPost

What the code could have been:

const { By } = require('selenium-webdriver');
const { Client } = require('selenium-webdriver/chrome');
const { Builder } = require('selenium-webdriver');
const loginReddit = require('./reddit login');
const getAllQuery = require('./selenium query');
const importLLM = require('./create llm session');
const puppeteer = require('puppeteer');

/**
 * Posts to a subreddit using Reddit's submit page.
 * 
 * @param {string} startPage The name of the subreddit to post to (e.g. 'r/test').
 * @param {string} content The content of the post.
 * @param {string|object|undefined} driver The Selenium WebDriver instance to use.
 * @throws {Error} If an error occurs during the posting process.
 */
async function redditPost(startPage, content, driver) {
  // Get the start page URL if the startPage parameter does not include '://'
  if (!startPage.includes('://')) {
    startPage = `https://www.reddit.com/r/${startPage}`;
  }

  // Append the post submission URL to the start page if not already present
  if (!startPage.includes('/submit')) {
    startPage += '/submit?type=TEXT';
  }

  // Initialize the Selenium driver if none is provided
  driver = driver || (await getClient());

  // Navigate to the post submission page
  await driver.get(startPage);

  // Log in to Reddit
  await loginReddit(driver);

  // Wait for a short period to allow the page to load
  await new Promise(resolve => setTimeout(resolve, 1500));

  // Extract the title from the content if it is marked up with Markdown headers
  let titleStr;
  const titleMatch = (/\*\*(.*?)\*\*\n*/gi).exec(content);
  if (titleMatch) {
    content = content.replace(titleMatch[0], '');
    titleStr = titleMatch[1].replaceAll(/[#*"']/gi, '');
  } else {
    // Otherwise, generate a title using the LLM
    const { llmPrompt } = await importLLM();
    titleStr = await llmPrompt('Generate a short title for this summary:\n' + content);
    titleStr = titleStr.replaceAll(/[#*"']/gi, '');
  }

  // Try to submit the post
  try {
    // Click into the title field
    const titleField = await driver.findElement(By.css('faceplate-textarea-input[name*="title"]'));
    await titleField.click();

    // Send the title to the title field
    await driver.actions().sendKeys(titleStr).perform();

    // Switch to Markdown mode
    const switchButton = await getAllQuery(driver, [
     'shreddit-composer',
      'button[aria-label*="Switch to Markdown"]',
    ]);
    await driver.executeScript('arguments[0].click();', switchButton[0]);
    await new Promise(resolve => setTimeout(resolve, 500));

    // Click into the body field
    const bodyField = await getAllQuery(driver, [
     'shreddit-composer',
     'shreddit-markdown-composer',
      'textarea[placeholder*="Body"]',
    ]);
    await driver.executeScript('arguments[0].click();', bodyField[0]);

    // Send the content to the body field
    await driver.actions().sendKeys(content).perform();

    // Submit the post
    const submitButton = await driver.findElement(By.css('#submit-post-button'));
    submitButton.click();

    // Wait for a short period to allow the post to be submitted
    await new Promise(resolve => setTimeout(resolve, 1500));
  } catch (error) {
    // TODO: Consider logging the error and quitting the driver if desired
    throw error;
  }
}

// Export the redditPost function
module.exports = redditPost;

// TODO: Consider implementing a retry mechanism for failed post submissions

// TODO: Consider adding a test suite for the redditPost function

// TODO: Consider refactoring the code to use a more robust error handling mechanism

Code Breakdown

Overview

This is a JavaScript function named redditPost that automates posting on Reddit using Selenium WebDriver. It takes three parameters: driver, content, and startPage.

Parameters

Functionality

  1. It checks if startPage is a valid URL and adds https://www.reddit.com/r/ if necessary.
  2. It checks if startPage ends with /submit and appends it if necessary.
  3. It logs into Reddit using the loginReddit function.
  4. It waits for 1.5 seconds using setTimeout.
  5. It extracts the title from the content string using a regular expression. If the title is not found, it uses the LLM (Large Language Model) to generate a title.
  6. It clears the title field and sets the title using the extracted or generated title.
  7. It clicks the "Switch to Markdown" button to enable Markdown formatting.
  8. It sets the body of the post using the content string.
  9. It submits the post by clicking the submit button.

Error Handling

The function catches any errors that occur during execution and re-throws them.

Export

The function is exported as a module using module.exports = redditPost.