Botmation Documentation
Overview
These functions focus on Instagram's web app, at desktop dimensions. Here is a working example.
These BotActions are designed in Instagram's web app running at desktop widths. The accessibility of some features differ in mobile then in desktop.
Install
In addition to installing @botmation/core, install @botmation/instagram:
npm i -s @botmation/instagram
All BotActions, URLs and selectors listed on this page, are exported by the @botmation/instagram
package.
Navigation
These BotActions focus on changing the URL of the Puppeteer page to specific locations within Instagram's web app.
goToHome
const goToHome: BotAction = goTo(INSTAGRAM_URL_BASE)
goToMessaging
const goToMessaging: BotAction = goTo(INSTAGRAM_URL_MESSAGING)
goToExplore
const goToExplore: BotAction = goTo(INSTAGRAM_URL_EXPLORE)
goToSettings
const goToSettings: BotAction = goTo(INSTAGRAM_URL_SETTINGS)
Auth
These BotAction's facilitate the login process of Instagram's web app.
login()
const login = ({username, password}: {username: string, password: string}): BotAction => chain( errors('Instagram login()')( goTo(getInstagramLoginUrl()), click(FORM_AUTH_USERNAME_INPUT_SELECTOR), type(username), click(FORM_AUTH_PASSWORD_INPUT_SELECTOR), type(password), click(FORM_AUTH_SUBMIT_BUTTON_SELECTOR), waitForNavigation, wait(1000), log('Login Complete') ) )
This BotAction is a composition that uses errors()() to wrap the main assembled BotAction's, in case something goes wrong here, dev's will have an easier time knowing if errors are thrown here.
The composition is declarative, therefore needs little explaining. login()
is a higher-order function that takes a typed object for the username
and password
.
isGuest
const isGuest: ConditionalBotAction = indexedDBStore('redux', 'paths')( getIndexedDBValue('users.viewerId'), map(viewerId => viewerId ? false : true), )
This BotAction is a composition that uses indexedDBStore()() to assemble BotAction's with the IndexedDB Database name and Store name injected. This simply grabs the value for the users.viewerId
key then maps it to the corresponding boolean value.
isLoggedIn
const isLoggedIn: ConditionalBotAction = indexedDBStore('redux', 'paths')( getIndexedDBValue('users.viewerId'), map(viewerId => viewerId ? true : false) )
This BotAction is a composition that uses indexedDBStore()() to assemble BotAction's with the IndexedDB Database name and Store name injected. This simply grabs the value for the users.viewerId
key then maps it to the corresponding boolean value.
logout
This function deletes cookies and local storage that include the user's session information, to effect a logout, upon page reload.
const logout: BotAction = pipe()( getCookies(), deleteCookies(), clearAllLocalStorage, reload())
isSaveYourLoginInfoActive
This BotAction tests the page for the "Save Your Login Info" flow that sometimes appears after initial login.
const isSaveYourLoginInfoActive: ConditionalBotAction = textExists('Save Your Login Info?')
clickSaveYourLoginInfoYesButton
This will close out the "Save Your Login Info" flow affirmatively.
const clickSaveYourLoginInfoYesButton: BotAction = clickText('Save Info')
clickSaveYourLoginInfoNoButton
This will close out the "Save Your Login Info" flow negatively.
const clickSaveYourLoginInfoNoButton: BotAction = clickText('Not Now')
Stories
These BotActions interact with the popular Instagram feature: Stories.
viewStories
This BotAction, when ran on the Home page, will view all available Stories from first to last, until complete.
const viewStories: BotAction = givenThat(elementExists(FIRST_STORY + ' button'))( click(FIRST_STORY + ' button'), wait(1000), forAsLong(elementExists(STORIES_VIEWER_NEXT_STORY_ICON))( click(STORIES_VIEWER_NEXT_STORY_ICON), wait(500) ) )
Modals
These BotAction's help handle Instagram's Modals.
isTurnOnNotificationsModalActive
const isTurnOnNotificationsModalActive: ConditionalBotAction = async(page) => { const modalHeader = await page.$(MAIN_MODAL_HEADER_SELECTOR) const modalHeaderText = await page.evaluate(el => el === null || el.textContent === null ? '' : el.textContent, modalHeader)
return modalHeader !== null && modalHeaderText === TURN_OFF_NOTIFICATIONS_MODAL_HEADER_TEXT}
Sometimes after login, Instagram prompts the User with a modal about turning on notifications. This ConditionalBotAction returns true
if that modal is open.
closeTurnOnNotificationsModal
const closeTurnOnNotificationsModal: BotAction = async (page) => { // click button with text "Not Now" inside the dialog const [button] = await page.$x("//button[contains(., '" + TURN_OFF_NOTIFICATIONS_BUTTON_LABEL + "')]") if (button) { await button.click() }}
This BotAction will close the "Turn on Notifications" modal. Please use givenThat()() with isTurnOnNotificationsModalActive to run this BotAction only if that modal is open.
Selectors
Helpful HTML element selectors in the Instagram web app, can be imported directly from the main botmation
package.
These are the following:
// Auth - Login Pageconst FORM_AUTH_USERNAME_INPUT_SELECTOR = 'html body section main form input[name="username"]'const FORM_AUTH_PASSWORD_INPUT_SELECTOR = 'html body section main form input[name="password"]'const FORM_AUTH_SUBMIT_BUTTON_SELECTOR = 'html body section main form button[type="submit"]'
// Modals - Home Pageconst MAIN_MODAL_SELECTOR = 'html body div[role="dialog"]'const MAIN_MODAL_HEADER_SELECTOR = 'html body div[role="dialog"] h2'
// Feed: Storiesconst FIRST_STORY = 'body main ul li[tabindex="-1"]'const STORIES_VIEWER_NEXT_STORY_ICON = 'body div section div div section div button div.coreSpriteRightChevron'
URLs
Here are some constants that represent specific pages within the Instagram web app:
const INSTAGRAM_URL_BASE = 'https://www.instagram.com/'
const INSTAGRAM_URL_LOGIN = INSTAGRAM_URL_BASE + 'accounts/login/'const INSTAGRAM_URL_MESSAGING = INSTAGRAM_URL_BASE + 'direct/inbox/'const INSTAGRAM_URL_EXPLORE = INSTAGRAM_URL_BASE + 'explore/'const INSTAGRAM_URL_SETTINGS = INSTAGRAM_URL_BASE + 'accounts/edit/'