Skip to content

Commit

Permalink
feat: Created tokenStore interface for session data management
Browse files Browse the repository at this point in the history
  • Loading branch information
edgardmessias committed Apr 14, 2021
1 parent 95ef716 commit a3a76c3
Show file tree
Hide file tree
Showing 33 changed files with 639 additions and 281 deletions.
3 changes: 1 addition & 2 deletions docs/getting-started/creating-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ wppconnect.create({
//Create session wss return "serverClose" case server for close
console.log('Session name: ', session);
},
folderNameToken: 'tokens', //folder name when saving tokens
mkdirFolderToken: '', //folder directory tokens, just inside the wppconnect folder, example: { mkdirFolderToken: '/node_modules', } //will save the tokens folder in the node_modules directory
folderNameToken: './tokens', //folder name when saving tokens
headless: true, // Headless chrome
devtools: false, // Open devtools by default
useChrome: true, // If false will use Chromium instance
Expand Down
2 changes: 1 addition & 1 deletion license-checker-config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"ignore": ["**/.*", "**/*.md", ".github"],
"ignore": ["**/.*", "**/*.md", ".github", ".husky", "api-docs", "tokens"],
"license": "LICENSE.header",
"licenseFormats": {
"js|ts": {
Expand Down
21 changes: 21 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
"puppeteer-extra": "^3.1.16",
"puppeteer-extra-plugin-stealth": "^2.6.6",
"qrcode-terminal": "^0.12.0",
"sanitize-filename": "^1.6.3",
"sharp": "^0.28.0",
"tree-kill": "^1.2.2",
"winston": "^3.3.3"
Expand Down
2 changes: 1 addition & 1 deletion src/api/helpers/decrypt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

import * as crypto from 'crypto';
import * as hkdf from 'futoin-hkdf';
import hkdf from 'futoin-hkdf';
import atob = require('atob');
import { ResponseType } from 'axios';

Expand Down
50 changes: 0 additions & 50 deletions src/api/helpers/delete-file.ts

This file was deleted.

2 changes: 0 additions & 2 deletions src/api/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,3 @@ export { stickerSelect, resizeImg } from './select-sticker';
export { scrapeImg } from './scrape-img-qr';
export { scrapeLogin } from './scrape-login';
export { scrapeDesconnected } from './scrape-desconnect';
export { scrapeDeleteToken } from './scrape-deletetoken';
export { deleteFiles } from './delete-file';
2 changes: 1 addition & 1 deletion src/api/helpers/select-sticker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* along with WPPConnect. If not, see <https://www.gnu.org/licenses/>.
*/

import * as sharp from 'sharp';
import sharp from 'sharp';

interface selectOutput {
webpBase64: string;
Expand Down
72 changes: 63 additions & 9 deletions src/api/layers/host.layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import { Page } from 'puppeteer';
import { CreateConfig, defaultOptions } from '../../config/create-config';
import { SocketState } from '../model/enum';
import { injectApi } from '../../controllers/browser';
import { initWhatsapp, injectApi } from '../../controllers/browser';
import { ScrapQrcode } from '../model/qrcode';
import { scrapeImg } from '../helpers';
import {
Expand All @@ -33,11 +33,19 @@ import { sleep } from '../../utils/sleep';
import { defaultLogger, LogLevel } from '../../utils/logger';
import { Logger } from 'winston';
import { CatchQRCallback, StatusFindCallback } from '../model';
import {
FileTokenStore,
isValidTokenStore,
MemoryTokenStore,
TokenStore,
} from '../../token-store';
import { isValidSessionToken } from '../../token-store/isValidSessionToken';

export class HostLayer {
readonly session: string;
readonly options: CreateConfig;
readonly logger: Logger;
readonly tokenStore: TokenStore;

protected autoCloseInterval = null;
protected statusFind?: StatusFindCallback = null;
Expand All @@ -48,15 +56,39 @@ export class HostLayer {

this.logger = this.options.logger || defaultLogger;

this.page.on('load', () => {
this.log('verbose', 'Page loaded', { type: 'page' });
this.initialize();
});
this.page.on('close', () => {
this.cancelAutoClose();
this.log('error', 'Page Closed', { type: 'page' });
});
if (typeof this.options.tokenStore === 'string') {
switch (this.options.tokenStore) {
case 'memory':
this.tokenStore = new MemoryTokenStore();
break;

case 'file':
default:
this.tokenStore = new FileTokenStore({
path: this.options.folderNameToken,
});
break;
}
} else {
this.tokenStore = this.options.tokenStore;
}

if (!isValidTokenStore(this.tokenStore)) {
this.log('warn', 'Invalid tokenStore, using default tokenStore', {
type: 'tokenStore',
});

if (this.options.folderNameToken) {
this.tokenStore = new FileTokenStore({
path: this.options.folderNameToken,
});
} else {
this.tokenStore = new MemoryTokenStore();
}
}

this.log('info', 'Initializing...');
this.initialize();
}

protected log(level: LogLevel, message: string, meta: object = {}) {
Expand All @@ -70,6 +102,28 @@ export class HostLayer {
}

protected async initialize() {
let sessionToken = this.options.sessionToken;
if (!sessionToken) {
sessionToken = await this.tokenStore.getToken(this.session);
}

if (isValidSessionToken(sessionToken)) {
this.log('verbose', 'Injecting session token', { type: 'token' });
}

await initWhatsapp(this.page, sessionToken);

this.page.on('load', () => {
this.log('verbose', 'Page loaded', { type: 'page' });
this.afterPageLoad();
});
this.page.on('close', () => {
this.cancelAutoClose();
this.log('error', 'Page Closed', { type: 'page' });
});
}

protected async afterPageLoad() {
this.log('verbose', 'Injecting wapi.js');
await injectApi(this.page)
.then(() => {
Expand Down
4 changes: 2 additions & 2 deletions src/api/layers/listener.layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ export class ListenerLayer extends ProfileLayer {
});
}

protected async initialize() {
await super.initialize();
protected async afterPageLoad() {
await super.afterPageLoad();

const functions = [
...Object.values(ExposedFn),
Expand Down
19 changes: 16 additions & 3 deletions src/api/layers/retriever.layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import { Page } from 'puppeteer';
import { CreateConfig } from '../../config/create-config';
import { tokenSession } from '../../config/tokenSession.config';
import { SessionToken } from '../../token-store';
import { WhatsappProfile } from '../model';
import { SenderLayer } from './sender.layer';

Expand All @@ -44,13 +44,26 @@ export class RetrieverLayer extends SenderLayer {
*/
public async getSessionTokenBrowser(
removePath?: boolean
): Promise<tokenSession> {
): Promise<SessionToken> {
if (removePath === true) {
await this.page.evaluate(() => {
window['pathSession'] = true;
});
}
return await this.page.evaluate(() => WAPI.getSessionTokenBrowser());

return await this.page
.evaluate(() => {
if (window.localStorage) {
return {
WABrowserId: window.localStorage.getItem('WABrowserId'),
WASecretBundle: window.localStorage.getItem('WASecretBundle'),
WAToken1: window.localStorage.getItem('WAToken1'),
WAToken2: window.localStorage.getItem('WAToken2'),
};
}
return null;
})
.catch(() => null);
}

/**
Expand Down
21 changes: 19 additions & 2 deletions src/api/model/initializer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
/*
* This file is part of WPPConnect.
*
* WPPConnect is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* WPPConnect is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with WPPConnect. If not, see <https://www.gnu.org/licenses/>.
*/
import { CreateConfig } from '../../config/create-config';
import { tokenSession } from '../../config/tokenSession.config';
import { SessionToken } from '../../token-store';
import { StatusFind } from './enum';

/**
Expand Down Expand Up @@ -35,6 +51,7 @@ export interface CreateOptions extends CreateConfig {
statusFind?: StatusFindCallback;
/**
* Pass the session token information you can receive this token with the await client.getSessionTokenBrowser () function
* @deprecated in favor of `sessionToken`
*/
browserSessionToken?: tokenSession;
browserSessionToken?: SessionToken;
}
35 changes: 35 additions & 0 deletions src/api/whatsapp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,45 @@ import { useragentOverride } from '../config/WAuserAgente';
import { CreateConfig } from '../config/create-config';
import axios from 'axios';
import treekill = require('tree-kill');
import { SocketState } from './model/enum';

export class Whatsapp extends ControlsLayer {
constructor(public page: Page, session?: string, options?: CreateConfig) {
super(page, session, options);

let connected = false;

this.onStateChange(async (state) => {
switch (state) {
case SocketState.CONNECTED:
connected = true;
// wait for localStore populate
setTimeout(async () => {
this.log('verbose', 'Updating session token', { type: 'token' });
const tokenData = await this.getSessionTokenBrowser();
this.tokenStore.setToken(this.session, tokenData);
}, 1000);
break;

case SocketState.UNPAIRED:
case SocketState.UNPAIRED_IDLE:
setTimeout(async () => {
this.log('info', 'Session Unpaired', { type: 'session' });
const removed = await this.tokenStore.removeToken(this.session);

if (removed) {
this.log('verbose', 'Token removed', { type: 'token' });
}

// Fire only after a success connection and disconnection
if (connected && this.statusFind) {
connected = false;
this.statusFind('desconnectedMobile', session);
}
}, 1000);
break;
}
});
}

/**
Expand Down
Loading

0 comments on commit a3a76c3

Please sign in to comment.