Botmation Documentation
IndexedDB
IndexedDB
These BotAction's interact with the Page's IndexedDB.
Except for the assembling indexedDBStore()(), these BotAction's are BotIndexedDBAction's. They are designed to accept customization through their higher-order params, injects, and even piping.
Higher-order params override all. Piping params override injects. Therefore, injects is a nice way to set the defaults for the majority, then on a case by case basis, can be overrideen by either other way.
IndexedDBStore
This sets the first few injects for BotIndexedDBAction's.
const indexedDBStore = (databaseName: string, storeName: string, databaseVersion?: number) => (...actions: BotAction<PipeValue|void>[]): BotAction<any> => pipe()( inject(databaseVersion, databaseName, storeName)( ...actions ) )
The second call assembles all BotAction's for running in a Pipe with the databaseVersion
, databaseName
, and storeName
injected, in that order.
This is not required, in order to assemble BotIndexedDBAction's. It simply allows you to express those injected values once, for the assembled BotAction's.
For an usage example, see the Instagram isGuest BotAction.
Set IndexedDB Value
This sets a value by key in a Store for a particular Database name and optionally version.
The storeName
, databaseName
, databaseVersion
can be passed through their higher-order params or by injecting. Higher-order params override injected ones.
The key
and value
can be passed through their higher-order params or by piping. Higher-order params override piped values.
const setIndexedDBValue = (key?: string, value?: any, storeName?: string, databaseName?: string, databaseVersion?: number): BotIndexedDBAction<void> => async(page, ...injects) => { const [pipedValue, injectDatabaseVersion, injectDatabaseName, injectStoreName] = unpipeInjects<getQueryKeyValue>(injects, 3)
if (!value) { if (pipedValue) { if (isObjectWithValue(pipedValue)) { value = pipedValue.value } else { value = pipedValue } } } if (!key) { if (isObjectWithKey(pipedValue)) { key = pipedValue.key } }
await page.evaluate( setIndexedDBStoreValue, databaseName ? databaseName : injectDatabaseName ? injectDatabaseName : 'missing-db-name', databaseVersion ? databaseVersion : injectDatabaseVersion ? injectDatabaseVersion : undefined, storeName ? storeName : injectStoreName ? injectStoreName : 'missing-store', key ? key : 'missing-key', value ? value : 'missing-value' ) }
If a value is missing to complete the operation, a safe
missing-*
default is used.
For an usage example, see Pipe BotAction.
Get IndexedDB Value
This gets a value by key in a Store for a particular Database name and optionally version.
The storeName
, databaseName
, databaseVersion
can be passed through their higher-order params or by injecting. Higher-order params override injected ones.
The key
and value
can be passed through their higher-order params or by piping. Higher-order params override piped values.
const getIndexedDBValue = (key?: string, storeName?: string, databaseName?: string, databaseVersion?: number): BotIndexedDBAction<PipeValue> => async(page, ...injects) => { const [pipeValue, injectDatabaseVersion, injectDatabaseName, injectStoreName] = unpipeInjects<getQueryKey>(injects, 3)
if (!key) { if (pipeValue) { if (isObjectWithKey(pipeValue)) { key = pipeValue.key } else { key = pipeValue } } }
return page.evaluate( getIndexedDBStoreValue, databaseName ? databaseName : injectDatabaseName ? injectDatabaseName : 'missing-db-name', databaseVersion ? databaseVersion : injectDatabaseVersion ? injectDatabaseVersion : undefined, storeName ? storeName : injectStoreName ? injectStoreName : 'missing-store', key ? key : 'missing-key' ) as PipeValue }
If a value is missing to complete the operation, a safe
missing-*
default is used.
For an usage example, see the Instagram isGuest BotAction.
Delete Indexed DB
This BotAction attempts to delete an IndexedDB database, provided the database name. It's possible for this to fail, you can read more about the used underlying logic here.
const deleteIndexedDB = (databaseName?: string): BotIndexedDBAction<void> => async(page, ...injects) => { const [, , injectDatabaseName] = unpipeInjects(injects, 2)
await page.evaluate( deleteIndexedDBDatabase, databaseName ?? injectDatabaseName )}
This BotAction is compatible with the indexedDBStore()() for injecting the name of the database for deletion.
Helpers
In order to interact with IndexedDB in the Puppeteer Page, separate functions are serialized and evaluated within the browser page. To accomplish this, the following Helper functions were created to be evaluated in the web pages.
If you
console.log()
in an evaluated Page function, the result will appear inside the browser's Console window and not the NodeJS terminal.
setIndexedDBStoreValue()
function setIndexedDBStoreValue(databaseName: string, databaseVersion: number, storeName: string, key: string, value: any) { return new Promise((resolve, reject) => {
const openRequest = indexedDB.open(databaseName, databaseVersion)
openRequest.onerror = function(this: IDBRequest<IDBDatabase>, ev: Event) { ev.stopPropagation() return reject(this.error) }
openRequest.onupgradeneeded = function(this: IDBOpenDBRequest, ev: IDBVersionChangeEvent): any { if (!this.result.objectStoreNames.contains(storeName)) { this.result.createObjectStore(storeName) } }
openRequest.onsuccess = function(this: IDBRequest<IDBDatabase>, ev: Event) { const db = this.result
try { db.transaction(storeName, 'readwrite') .objectStore(storeName) .put(value, key) .onsuccess = function(this, ev) { db.close() return resolve() } } catch (error) { db.close() return reject(error) } } })}
getIndexedDBStoreValue()
function getIndexedDBStoreValue(databaseName: string, databaseVersion: number, storeName: string, key: string) { return new Promise((resolve, reject) => { const openRequest = indexedDB.open(databaseName, databaseVersion)
openRequest.onerror = function(this: IDBRequest<IDBDatabase>, ev: Event) { return reject(this.error) }
openRequest.onsuccess = function(this: IDBRequest<IDBDatabase>, ev: Event) { const db = this.result
try { const tx = db.transaction(storeName, 'readonly') .objectStore(storeName) .get(key)
tx.onsuccess = function(this: IDBRequest<any>, ev: Event) { const result = this.result db.close() return resolve(result) }
} catch (error) { db.close() return reject(error) } } })}
deleteIndexedDBDatabase()
function deleteIndexedDBDatabase(databaseName: string) { return new Promise<void>((resolve, reject) => { const DBDeleteRequest = indexedDB.deleteDatabase(databaseName);
DBDeleteRequest.onerror = function(event) { logError('delete IndexedDB Database name = ' + databaseName) event.stopPropagation() return reject(this.error) };
DBDeleteRequest.onsuccess = function() { return resolve() };
DBDeleteRequest.onblocked = function(event) { event.stopPropagation() logMessage('blocked attempt to delete IndexedDB Database name = ' + databaseName) return resolve() }; })}