Skip to content

Commit

Permalink
Instagram viewStories (#105)
Browse files Browse the repository at this point in the history
* instagram & core botactions/helpers

- viewStories 
- instagram navigation botactions
- instagram save your login info UX botactions
- elementExistsInDocument & textExistsInDocument helpers
- elementExists, textExists botactions

* bug fix - edge case for no element found in $ botaction #102

* clickText

* clickElementWithText helper

* fix #102 $$ multiple elements scraping

- undefined edge case will not attempt to parse undefine but return
undefined

* botactions getCookies & deleteCookies & instagram logout

- used in tandem in a pipe to delete cookies for urls associated with a
browser page
   - this in replace of deleteAllCookiesForCurrentUrl BotAction

* instagram logout

* deleteIndexedDB by database name

* e2e test $() for not finding html node

- edge-case behavior modified -> originally threw error, now returns
undefined

* e2e test textExists & elementExists

* e2e clickText

- ignore serialized code injected into puppeteer, covered by e2e

* e2e clickText edge-case

* integration test getCookies

* integration test deleteCookies

* e2e cookies testing

* rollDice()() BotAction #85

- run assembled botactions if a virtual dice with X sides rolls a 1
   - number of sides X is set via HO param, default is 1
   - number to roll can be set via 2nd HO param, default is 1

* helper diceRoll() unit-test

- added edge-case for dice with zero or negative number of sides which
on roll, returns 0

* probably() botaction - new established BotAction group: Random

- randomDecimal helper using pseudo Math.random()
- rollDice() has probability limitation of no probabilities greater than
50% therefore need another botaction
- rollDice()() uses probably()()

- randomDiceRoll() helper similar to randomDecimal() helper

* added ability to override random decimal function

- if prefer not pseudo random ie random derived via buffer/crypto then
set your own function in the helper
- probably()() HO 2nd param (optional) to override random number generator
- instead of using pseudo random number generating, use a
buffer/crypto/other

* randomDecimal HO injector for overriding the default pseudo random generating function

* not going to force pipe() on randomDecimal()() injector

- similar to files()(), because indexedDB has botactions that rely on
piping, and the context might be a chain, so with that you want to
enforce pipe because it makes sense (however arugably oppose it can be
said)

* unit & integration tests

- BotActions group Random: randomDecimal()(), rollDice()(), probably()()

* random botactions test coverage

* indexed-db e2e testing

* house cleaning

* code smells

* Nullish Assignment

* simplify goTo implementation

* readmes updated

* consolidated instagram URL helpers into simpler constants

* fix instagram barrel + desktop widths

* new published minor versions for core and instagram pckgs

- instagram reference latest core pckg
  • Loading branch information
mrWh1te authored Apr 21, 2021
1 parent 1e2a5bb commit 3835d41
Show file tree
Hide file tree
Showing 41 changed files with 917 additions and 234 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
## v1.3.0 @botmation/core

New BotActions group called "Random" for running BotActions on a probability.

Couple bug fixes.

New auxiliary Instagram package v1.1.0:
- navigation
- view stories
- logout

More details [here](https://github.com/mrWh1te/Botmation/pull/105).

## v1.2.0 @botmation/core

New BotAction called [restart](https://www.botmation.dev/api/abort#restart) for restarting an assembled lines of BotActions that aborts.

Added support for latest major Puppeteer v8.

More details [here](https://github.com/mrWh1te/Botmation/pull/97).

## v1.1.0 @botmation/core

New `schedule()` BotAction, reorganization of BotAction groups (Utilities => Time, Loops, Branching) and minor performance improvement of a few core BotActions.
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Import any core API function from:
import { chain, goTo, screenshot } from '@botmation/core'
```

`@botmation/core` v1 has 16 groups of BotActions to choose from:
`@botmation/core` v1 has 17 groups of BotActions to choose from:

<img alt="Leader Bot" src="https://raw.githubusercontent.com/mrWh1te/Botmation/master/assets/art/red_bot.PNG" width="200" align="right" style="position: relative;top: 30px;">

Expand Down Expand Up @@ -98,6 +98,8 @@ import { chain, goTo, screenshot } from '@botmation/core'
- change the page's URL, wait for form submissions to change page URL, back, forward, refresh
- [pipe](https://www.botmation.dev/api/pipe)
- functions specific to Piping
- [random](https://www.botmation.dev/api/random)
- functions specific to randomness like rolling dice
- [scrapers](https://www.botmation.dev/api/scrapers)
- scrape HTML documents with an HTML parser and evaluate JavaScript inside a Page
- [time](https://www.botmation.dev/api/time)
Expand Down
46 changes: 34 additions & 12 deletions apps/bot-instagram/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import {
givenThat,
loadCookies,
saveCookies,
goTo,
screenshot,
logError
logError,
waitForNavigation,
wait,
} from '@botmation/core'

import {
Expand All @@ -18,7 +19,10 @@ import {
isLoggedIn,
closeTurnOnNotificationsModal,
isTurnOnNotificationsModalActive,
getInstagramBaseUrl
goToHome,
viewStories,
isSaveYourLoginInfoActive,
clickSaveYourLoginInfoNoButton,
} from '@botmation/instagram'

(async () => {
Expand All @@ -29,17 +33,26 @@ import {
const pages = await browser.pages()
const page = pages.length === 0 ? await browser.newPage() : pages[0]

// Instagram BotActions were developed for the UI responsiveness in desktop widths
// specifically, in mobile widths, the `viewStories` BotAction will open your story
// instead of the presentation of stories
await page.setViewport({
width: 1000,
height: 600,
deviceScaleFactor: 1,
});

await chain(
log('Botmation running'),

// Sets up the injects for BotFileAction's (optional)
files({cookies_directory: 'simple'})(
files()(
// Takes the name of the file to load cookies from
// Match this value with the same used in saveCookies()
loadCookies('instagram'),
),

goTo(getInstagramBaseUrl()),
goToHome,

// inline, hackish but do-able if your doing something on the fly
// follow the rules, don't return a value in a chain
Expand All @@ -48,26 +61,35 @@ import {
// },

// lets log in, if we are a guest
log('checking Guest status'),
givenThat(isGuest) (
log('is guest so logging in'),
login({username: 'account', password: 'password'}), // <- put your username and password here
files({cookies_directory: 'simple'})(
saveCookies('instagram'), // the Bot will skip login, on next run, by loading cookies
files()(
saveCookies('instagram'), // the Bot will skip login, on next run, by loading the cookies from this file
),
log('Saved Cookies')
),

// in case that log in failed, lets check before we operate as a logged in user
givenThat(isLoggedIn)(
log('is logged in'),
// After initial load, Instagram sometimes prompts the User with a modal...

givenThat(isSaveYourLoginInfoActive)(
clickSaveYourLoginInfoNoButton,
waitForNavigation,
log('save ur login info closed')
),

// Deal with the "Turn On Notifications" Modal, if it shows up
givenThat(isTurnOnNotificationsModalActive)(
closeTurnOnNotificationsModal
),

screenshot('logged-in'),

viewStories,

log('screenshot taken'),

wait(5000),

),

log('Done'),
Expand Down
35 changes: 35 additions & 0 deletions assets/server/cookies.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Testing: Cookies
</title>
<script type="text/javascript">
document.cookie = "username=John Doe";
document.cookie = "sessionId=1235711"
</script>
</head>
<body>
<h1>Cookies Page</h1>
<aside>
<ul>
<li>
<a href="/index.html" class="home-link">Home Link</a>
</li>
<li>
<a href="/example.html" class="example-link">Example Link</a>
</li>
<li>
<a href="/example2.html" class="example-link">Example Link 2</a>
</li>
</ul>
</aside>
<section>
<form action="/success.html">
<input type="text" name="answer" />
<button type="submit">
Click Me!
</button>
</form>
</section>
</body>
</html>
79 changes: 79 additions & 0 deletions assets/server/indexed-db.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Testing: IndexedDB</title>
<script type="text/javascript">
const databaseName = 'MyTestDatabase';
const databaseName2 = 'MySecondDatabase';
const databaseVersion = undefined;
const storeName = 'TestObjectStore';
const key = 'TestKey';
const value = 'TestValue234';

const openRequest = indexedDB.open(databaseName, databaseVersion);

openRequest.onerror = function(ev) {
ev.stopPropagation();
console.error(openRequest.error);
}

openRequest.onupgradeneeded = function(ev) {
if (!openRequest.result.objectStoreNames.contains(storeName)) {
openRequest.result.createObjectStore(storeName);
}
}

openRequest.onsuccess = function(ev) {
const db = openRequest.result;

try {
db.transaction(storeName, 'readwrite')
.objectStore(storeName)
.put(value, key)
.onsuccess = function() {
db.close();
}
} catch (error) {
db.close();
}
}

const openRequest2 = indexedDB.open(databaseName2);

openRequest2.onerror = function(ev) {
ev.stopPropagation();
console.error(openRequest2.error);
}

openRequest2.onupgradeneeded = function(ev) {
if (!openRequest2.result.objectStoreNames.contains(storeName)) {
openRequest2.result.createObjectStore(storeName);
}
}

openRequest2.onsuccess = function(ev) {
const db = openRequest2.result;

try {
db.transaction(storeName, 'readwrite')
.objectStore(storeName)
.put(value, key)
.onsuccess = function() {
db.close();
}
} catch (error) {
db.close();
}
}
</script>
</head>
<body>
<h1>IndexedDB</h1>
<ul>
<li>DB name: MyTestDatabase</li>
<li>Store name: TestObjectStore</li>
<li>Key: TestKey</li>
<li>Key Value: TestValue234</li>
</ul>
</body>
</html>
4 changes: 3 additions & 1 deletion libs/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Import any core API function from:
import { chain, goTo, screenshot } from '@botmation/core'
```

`@botmation/core` v1 has 16 groups of BotActions to choose from:
`@botmation/core` v1 has 17 groups of BotActions to choose from:

<img alt="Leader Bot" src="https://raw.githubusercontent.com/mrWh1te/Botmation/master/assets/art/red_bot.PNG" width="200" align="right" style="position: relative;top: 30px;">

Expand Down Expand Up @@ -104,6 +104,8 @@ import { chain, goTo, screenshot } from '@botmation/core'
- change the page's URL, wait for form submissions to change page URL, back, forward, refresh
- [pipe](https://www.botmation.dev/api/pipe)
- functions specific to Piping
- [random](https://www.botmation.dev/api/random)
- functions specific to randomness like rolling dice
- [scrapers](https://www.botmation.dev/api/scrapers)
- scrape HTML documents with an HTML parser and evaluate JavaScript inside a Page
- [time](https://www.botmation.dev/api/time)
Expand Down
2 changes: 1 addition & 1 deletion libs/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@botmation/core",
"version": "1.2.1",
"version": "1.3.0",
"description": "Main package of functions for the TypeScript framework Botmation",
"homepage": "https://botmation.dev",
"author": "Michael Lage",
Expand Down
3 changes: 3 additions & 0 deletions libs/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export * from './lib/actions/scrapers'
export * from './lib/actions/loops'
export * from './lib/actions/branching'
export * from './lib/actions/time'
export * from './lib/actions/random'

//
// Helpers
Expand All @@ -36,8 +37,10 @@ export * from './lib/helpers/cases'
export * from './lib/helpers/console'
export * from './lib/helpers/files'
export * from './lib/helpers/indexed-db'
export * from './lib/helpers/input'
export * from './lib/helpers/local-storage'
export * from './lib/helpers/navigation'
export * from './lib/helpers/pipe'
export * from './lib/helpers/scrapers'
export * from './lib/helpers/cases'
export * from './lib/helpers/random'
10 changes: 5 additions & 5 deletions libs/core/src/lib/actions/abort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ export const restart = (...actions: BotAction<any>[]): BotAction<any> =>
// manually resolving actions in a Pipe instead of using pipe()() to control the AbortLineSignal processing
actionResult = await action(page, ...injects, pipeObject)

// unique recycle aborting behavior
// unique restart aborting behavior
if (isAbortLineSignal(actionResult)) {
// cannot recycle an infinity abort, if desirable, create another BotAction - maybe with a customizing HO function
// assembledLines 1 => recycle actions
// assembledLines 0 or 2+ => abort recycle
// cannot restart an infinity abort, if desirable, create another BotAction - maybe with a customizing HO function
// assembledLines 1 => restart actions
// assembledLines 0 or 2+ => abort restart
if (actionResult.assembledLines > 1 || actionResult.assembledLines === 0) {
return processAbortLineSignal(actionResult, 2) // abort the line and abort recycle()
return processAbortLineSignal(actionResult, 2) // abort the line and abort restart()
} else {
restartActions = true;
pipeObject = wrapValueInPipe(actionResult.pipeValue)
Expand Down
1 change: 1 addition & 0 deletions libs/core/src/lib/actions/branching.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ export const givenThat =
}
}
}

2 changes: 1 addition & 1 deletion libs/core/src/lib/actions/console.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('[Botmation] actions/console', () => {
page = await browser.newPage()
})

afterEach(async () => {
afterEach(async() => {
await page.close()
})

Expand Down
Loading

0 comments on commit 3835d41

Please sign in to comment.