Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-device Branch #889

Merged
merged 124 commits into from
Feb 27, 2022
Merged

Multi-device Branch #889

merged 124 commits into from
Feb 27, 2022

Conversation

PurpShell
Copy link
Sponsor Collaborator

@PurpShell PurpShell commented Sep 16, 2021

Update

Multidevice support is now released on v1.16+. Please install the latest version of the library through npm and you should be good to go. Checkout the 1.16 release notes at https://github.com/pedroslopez/whatsapp-web.js/releases/tag/v1.16.0 for more information.

Previous content

To do:

  • fix: client.isRegisteredUser
  • fix: buttons and lists
  • feat: Templates (if possible)
  • fix: group functions (promote, demote, kick, add) functions in MD (Module not found yet)
  • fix: linkPreview generation broken when sending message with a link in it.

Updated PR.

How to use / permanent changes:

Install via npm i github:pedroslopez/whatsapp-web.js#multidevice

  1. Heroku is no longer supported. Basically they follow a ephemeral file system, and it resets each time the app restarts and we rely on constantly updated data to keep messages, chats, even the session itself. Unless you have a DB that you can update at MILLESECOND intervals, I am pretty positive that Heroku hosting is done for.
  2. As said above, the session now uses the filesystem, so for code this is what you have to do, take this example:
const SESSION_FILE_PATH = './session.json';
let sessionCfg;
if (fs.existsSync(SESSION_FILE_PATH)) {
    sessionCfg = require(SESSION_FILE_PATH);
}

const client = new Client({ puppeteer: { headless: false }, session: sessionCfg });
// You can use an existing session and avoid scanning a QR code by adding a "session" object to the client options.
// This object must include WABrowserId, WASecretBundle, WAToken1 and WAToken2.

// You also could connect to an existing instance of a browser
// { 
//    puppeteer: {
//        browserWSEndpoint: `ws://localhost:3000`
//    }
// }

client.initialize();

client.on('qr', (qr) => {
    // NOTE: This event will not be fired if a session is specified.
    console.log('QR RECEIVED', qr);
});

client.on('authenticated', (session) => {
    console.log('AUTHENTICATED', session);
    sessionCfg=session;
    fs.writeFile(SESSION_FILE_PATH, JSON.stringify(session), function (err) {
        if (err) {
            console.error(err);
        }
    });
});

client.on('auth_failure', msg => {
    // Fired if session restore was unsuccessfull
    console.error('AUTHENTICATION FAILURE', msg);
});

client.on('ready', () => {
    console.log('READY');
});

client.on('message', async msg => {
    console.log('MESSAGE RECEIVED', msg);
});

client.on('message_create', (msg) => {
    // Fired on all message creations, including your own
    if (msg.fromMe) {
        // do stuff here
    }
});

client.on('message_revoke_everyone', async (after, before) => {
    // Fired whenever a message is deleted by anyone (including you)
    console.log(after); // message after it was deleted.
    if (before) {
        console.log(before); // message before it was deleted.
    }
});

client.on('message_revoke_me', async (msg) => {
    // Fired whenever a message is only deleted in your own view.
    console.log(msg.body); // message before it was deleted.
});

client.on('message_ack', (msg, ack) => {
    /*
        == ACK VALUES ==
        ACK_ERROR: -1
        ACK_PENDING: 0
        ACK_SERVER: 1
        ACK_DEVICE: 2
        ACK_READ: 3
        ACK_PLAYED: 4
    */

    if(ack == 3) {
        // The message was read
    }
});

client.on('group_join', (notification) => {
    // User has joined or been added to the group.
    console.log('join', notification);
    notification.reply('User joined.');
});

client.on('group_leave', (notification) => {
    // User has left or been kicked from the group.
    console.log('leave', notification);
    notification.reply('User left.');
});

client.on('group_update', (notification) => {
    // Group picture, subject or description has been updated.
    console.log('update', notification);
});

client.on('change_battery', (batteryInfo) => {
    // Battery percentage for attached device has changed
    const { battery, plugged } = batteryInfo;
    console.log(`Battery: ${battery}% - Charging? ${plugged}`);
});

client.on('change_state', state => {
    console.log('CHANGE STATE', state );
});

client.on('disconnected', (reason) => {
    console.log('Client was logged out', reason);
});

becomes like this:

const client = new Client({ puppeteer: { headless: false }, clientId: 'example' });
client.initialize();

client.on('qr', (qr) => {
    // NOTE: This event will not be fired if a session is specified.
    console.log('QR RECEIVED', qr);
});

client.on('authenticated', () => {
    console.log('AUTHENTICATED');
});

client.on('auth_failure', msg => {
    // Fired if session restore was unsuccessfull
    console.error('AUTHENTICATION FAILURE', msg);
});

client.on('ready', () => {
    console.log('READY');
});

client.on('message', async msg => {
    console.log('MESSAGE RECEIVED', msg);
});

client.on('message_create', (msg) => {
    // Fired on all message creations, including your own
    if (msg.fromMe) {
        // do stuff here
    }
});

client.on('message_revoke_everyone', async (after, before) => {
    // Fired whenever a message is deleted by anyone (including you)
    console.log(after); // message after it was deleted.
    if (before) {
        console.log(before); // message before it was deleted.
    }
});

client.on('message_revoke_me', async (msg) => {
    // Fired whenever a message is only deleted in your own view.
    console.log(msg.body); // message before it was deleted.
});

client.on('message_ack', (msg, ack) => {
    /*
        == ACK VALUES ==
        ACK_ERROR: -1
        ACK_PENDING: 0
        ACK_SERVER: 1
        ACK_DEVICE: 2
        ACK_READ: 3
        ACK_PLAYED: 4
    */

    if(ack == 3) {
        // The message was read
    }
});

client.on('group_join', (notification) => {
    // User has joined or been added to the group.
    console.log('join', notification);
    notification.reply('User joined.');
});

client.on('group_leave', (notification) => {
    // User has left or been kicked from the group.
    console.log('leave', notification);
    notification.reply('User left.');
});

client.on('group_update', (notification) => {
    // Group picture, subject or description has been updated.
    console.log('update', notification);
});

client.on('change_state', state => {
    console.log('CHANGE STATE', state );
});

client.on('disconnected', (reason) => {
    console.log('Client was logged out', reason);
});

Meaning, there is no longer a session JSON that is given on auth nor is there change battery info. (also no longer phone info (ClientInfo.phone))

  1. For now, Remote Browser / Browserless is not supported.

@PurpShell PurpShell changed the title Multi-device Branch merge (#888) Multi-device Branch Sep 16, 2021
@ricardoapaes
Copy link
Contributor

I tested it here and it worked perfectly.

Thanks

@crboschi74
Copy link

Hello
I receive this error

AUTHENTICATED undefined
(node:22904) UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined
at Object.writeFile (fs.js:1436:5)
at Client. (C:\newtec\waw\wanx.js:32:8)
at Client.emit (events.js:315:20)
at Client.initialize (C:\newtec\waw\node_modules\whatsapp-web.js\src\Client.js:167:14)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use node --trace-warnings ... to show where the warning was created)
(node:22904) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:22904) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

@ricardoapaes
Copy link
Contributor

Hello
I receive this error

AUTHENTICATED undefined
(node:22904) UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined
at Object.writeFile (fs.js:1436:5)
at Client. (C:\newtec\waw\wanx.js:32:8)
at Client.emit (events.js:315:20)
at Client.initialize (C:\newtec\waw\node_modules\whatsapp-web.js\src\Client.js:167:14)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use node --trace-warnings ... to show where the warning was created)
(node:22904) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:22904) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

@crboschi74

I believe that the error reported does not occur in the library, on the line: "whatsapp-web.js\src\Client.js:167:14" the event "Events.AUTHENTICATED" is launched and that calls something that was written by you in

"C:\newtec\waw\wanx.js:32:8"
Looks to me like you're passing a variable of the wrong type, check your code.

@crboschi74
Copy link

Hello
I receive this error
AUTHENTICATED undefined
(node:22904) UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined
at Object.writeFile (fs.js:1436:5)
at Client. (C:\newtec\waw\wanx.js:32:8)
at Client.emit (events.js:315:20)
at Client.initialize (C:\newtec\waw\node_modules\whatsapp-web.js\src\Client.js:167:14)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use node --trace-warnings ... to show where the warning was created)
(node:22904) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:22904) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

@crboschi74

I believe that the error reported does not occur in the library, on the line: "whatsapp-web.js\src\Client.js:167:14" the event "Events.AUTHENTICATED" is launched and that calls something that was written by you in

"C:\newtec\waw\wanx.js:32:8"
Looks to me like you're passing a variable of the wrong type, check your code.

ok
but the session? how to save ?

@ricardoapaes
Copy link
Contributor

Hello
I receive this error
AUTHENTICATED undefined
(node:22904) UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined
at Object.writeFile (fs.js:1436:5)
at Client. (C:\newtec\waw\wanx.js:32:8)
at Client.emit (events.js:315:20)
at Client.initialize (C:\newtec\waw\node_modules\whatsapp-web.js\src\Client.js:167:14)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use node --trace-warnings ... to show where the warning was created)
(node:22904) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:22904) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

@crboschi74
I believe that the error reported does not occur in the library, on the line: "whatsapp-web.js\src\Client.js:167:14" the event "Events.AUTHENTICATED" is launched and that calls something that was written by you in
"C:\newtec\waw\wanx.js:32:8"
Looks to me like you're passing a variable of the wrong type, check your code.

ok
but the session? how to save ?

@crboschi74

Now you no longer need to enter the "session" parameter, the session data is saved in the folder informed in the "dataPath" attribute, if this attribute is omitted it will create a "WWebJS" folder in the project root saving the puppeteer session data.

You can also enter a "clienteId" parameter to separate it into several distinct sessions.

* @param {string} options.dataPath - Change the default path for saving session files, default is: "./WWebJS/"

@JeffPatricio JeffPatricio mentioned this pull request Sep 18, 2021
@PurpShell
Copy link
Sponsor Collaborator Author

Hello
I receive this error
AUTHENTICATED undefined
(node:22904) UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined
at Object.writeFile (fs.js:1436:5)
at Client. (C:\newtec\waw\wanx.js:32:8)
at Client.emit (events.js:315:20)
at Client.initialize (C:\newtec\waw\node_modules\whatsapp-web.js\src\Client.js:167:14)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use node --trace-warnings ... to show where the warning was created)
(node:22904) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:22904) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

@crboschi74
I believe that the error reported does not occur in the library, on the line: "whatsapp-web.js\src\Client.js:167:14" the event "Events.AUTHENTICATED" is launched and that calls something that was written by you in
"C:\newtec\waw\wanx.js:32:8"
Looks to me like you're passing a variable of the wrong type, check your code.

ok
but the session? how to save ?

You can't save the session, if you have more than one session you can pass in the clientId option to differentiate sessions.

@Luxemburgo
Copy link

Luxemburgo commented Sep 22, 2021

Hi! Thanks for all your work.

I'm getting this issue

image
(WhatsApp works with Google Chrome 60+)

I already updated Puppeteer to the last version (10.4) but the issue continues

@Luxemburgo
Copy link

Hi! Thanks for all your work.

I'm getting this issue

image
(WhatsApp works with Google Chrome 60+)

I already updated Puppeteer to the last version (10.4) but the issue continues

Sorry, aprently was a problem of cahce (or cookies, etc). I deleted it all and now it works.

@pedroslopez pedroslopez merged commit 0d55d40 into main Feb 27, 2022
@pedroslopez pedroslopez deleted the multidevice branch February 27, 2022 22:51
@pedroslopez pedroslopez restored the multidevice branch February 27, 2022 22:51
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet