pedroslopez / whatsapp-web.js

A WhatsApp client library for NodeJS that connects through the WhatsApp Web browser app
https://wwebjs.dev
Apache License 2.0
15.46k stars 3.69k forks source link

Multiple sessions #45

Closed fernandolcardoso closed 4 years ago

fernandolcardoso commented 4 years ago

I'm trying to initialize the script in multiple sessions, does anyone have any tips?

const {Client} = require(`./1.0.1/index`);
const fs = require(`fs`);

const session = function (number) {

    console.log('number', number);

    const client = new Client({
        puppeteer: {
            headless: false,
            userDataDir: __dirname + `/${number}`,
            args: ['--no-sandbox']
        },
        session: function () {
            if (fs.existsSync(`./${number}.json`))
                return require(`./${number}.json`);
            else return false;
        }
    });

    client.initialize();

    client.on(`qr`, (qr) => {
        console.log('qr', qr);
    });

    client.on(`authenticated`, (session) => {
        if (!fs.existsSync(`./${number}.json`)) {
            fs.writeFile(`./${number}.json`, JSON.stringify(session), function (err) {
                if (err) console.log(err);
                else console.log(`Session stored`);
            });
        }
    });

    client.on(`auth_failure`, (msg) => {
        console.log(`auth_failure`, msg);
    });

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

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

    client.on(`disconnected`, (reason) => {
        console.log(`disconnected`, reason);
    });

};

new session('phone-number');
pedroslopez commented 4 years ago

There shouldn't be an issue with handling multiple sessions. You'll just want to instantiate multiple clients.

const client = new Client();
const client2 = new Client();

client.initialize();
client2.initialize();

client.on('qr', qr => {
    console.log('QR Received (1)', qr);
});

client2.on('qr', qr => {
    console.log('QR Received (2)', qr);
});

If you want to use the same handlers, you can define a function separately and register the handler like so:

const onMessage = (msg) => {
    console.log(msg.body);
}

client.on('message', onMessage);
client2.on('message', onMessage);

Is this what you're referring to?

fernandolcardoso commented 4 years ago

@pedroslopez Thanks for the contribution, did you see my example? Was there a possibility to create something this way?

pedroslopez commented 4 years ago

Yeah I don't see why that wouldn't work. You can also return the client from that function so you can access it later.

Is something wrong with the solution you posted?

pedroslopez commented 4 years ago

Also, just as a note, every WhatsApp structure has the client reference so if at any point you have, for example, a Message object, you can get the client it refers to by using message.client.

fernandolcardoso commented 4 years ago

@pedroslopez I'm running tests and I had some session problems, so I'm separating the puppeteer's cache in the variable.

fernandolcardoso commented 4 years ago

Great, I found my error in the session and the puppeteer started 2 separate browsers with cache.

I applied only one fix to get the file with the keys.

image

fernandolcardoso commented 4 years ago

The corrected version follows with multiple sessions.


const {Client} = require(`./1.0.1/index`);
const fs = require(`fs`);

const session = function (number) {

    console.log('number', number);

    let session_file;
    if (fs.existsSync(`./${number}.json`)) {
        session_file = require(`./${number}.json`);
        console.log('session_file', session_file);
    }

    const client = new Client({
        puppeteer: {
            headless: false,
            userDataDir: __dirname + `/${number}`,
            args: ['--no-sandbox']
        },
        session: session_file
    });

    client.initialize();

    client.on(`qr`, (qr) => {
        console.log('qr', qr);
    });

    client.on(`authenticated`, (session) => {
        if (!fs.existsSync(`./${number}.json`)) {
            fs.writeFile(`./${number}.json`, JSON.stringify(session), function (err) {
                if (err) console.log(err);
                else console.log(`Session stored`);
            });
        }
    });

    client.on(`auth_failure`, (msg) => {
        console.log(`auth_failure`, msg);
    });

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

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

    client.on(`disconnected`, (reason) => {
        console.log(`disconnected`, reason);
    });

};

new session('phone-number-1');
new session('phone-number-2');
new session('phone-number-3');

It would be interesting to implement this script in the examples.

pedroslopez commented 4 years ago

Yeah, definitely!

I'm in the process right now of creating a nice and clear guide that explains how everything works (https://waguide.pedroslopez.me/). I just started it a few hours ago so it's still in progress, but eventually I want to move away from pointing people to example.js and have everything in that guide. I'm thinking of having a useful examples section in there where something like this can go.

Thanks!

radenvodka commented 4 years ago

The corrected version follows with multiple sessions.

const {Client} = require(`./1.0.1/index`);
const fs = require(`fs`);

const session = function (number) {

  console.log('number', number);

  let session_file;
  if (fs.existsSync(`./${number}.json`)) {
      session_file = require(`./${number}.json`);
      console.log('session_file', session_file);
  }

  const client = new Client({
      puppeteer: {
          headless: false,
          userDataDir: __dirname + `/${number}`,
          args: ['--no-sandbox']
      },
      session: session_file
  });

  client.initialize();

  client.on(`qr`, (qr) => {
      console.log('qr', qr);
  });

  client.on(`authenticated`, (session) => {
      if (!fs.existsSync(`./${number}.json`)) {
          fs.writeFile(`./${number}.json`, JSON.stringify(session), function (err) {
              if (err) console.log(err);
              else console.log(`Session stored`);
          });
      }
  });

  client.on(`auth_failure`, (msg) => {
      console.log(`auth_failure`, msg);
  });

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

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

  client.on(`disconnected`, (reason) => {
      console.log(`disconnected`, reason);
  });

};

new session('phone-number-1');
new session('phone-number-2');
new session('phone-number-3');

It would be interesting to implement this script in the examples.

how do you send messages with a particular session?

PetrosM263 commented 4 years ago

Thus interesting I also have the same idea as yours. I will try your code and see if I can do some up grades

On Mon, Apr 6, 2020, 06:03 ʀᴀᴅᴇɴᴠᴏᴅᴋᴀ (ᴇᴋᴀ ꜱ) notifications@github.com wrote:

The corrected version follows with multiple sessions.

const {Client} = require(./1.0.1/index);const fs = require(fs); const session = function (number) {

console.log('number', number);

let session_file; if (fs.existsSync(./${number}.json)) { session_file = require(./${number}.json); console.log('session_file', session_file); }

const client = new Client({ puppeteer: { headless: false, userDataDir: __dirname + /${number}, args: ['--no-sandbox'] }, session: session_file });

client.initialize();

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

client.on(authenticated, (session) => { if (!fs.existsSync(./${number}.json)) { fs.writeFile(./${number}.json, JSON.stringify(session), function (err) { if (err) console.log(err); else console.log(Session stored); }); } });

client.on(auth_failure, (msg) => { console.log(auth_failure, msg); });

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

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

client.on(disconnected, (reason) => { console.log(disconnected, reason); });

}; new session('phone-number-1');new session('phone-number-2');new session('phone-number-3');

It would be interesting to implement this script in the examples.

how do you send messages with a particular session?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/pedroslopez/whatsapp-web.js/issues/45#issuecomment-609553345, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANMBORL5P2HW42ZTP3HISSLRLFICRANCNFSM4KSYHMAA .

asepwaee commented 4 years ago

How i do send message with different route using thats multi session code ?

asepwaee commented 4 years ago

The corrected version follows with multiple sessions.

const {Client} = require(`./1.0.1/index`);
const fs = require(`fs`);

const session = function (number) {

    console.log('number', number);

    let session_file;
    if (fs.existsSync(`./${number}.json`)) {
        session_file = require(`./${number}.json`);
        console.log('session_file', session_file);
    }

    const client = new Client({
        puppeteer: {
            headless: false,
            userDataDir: __dirname + `/${number}`,
            args: ['--no-sandbox']
        },
        session: session_file
    });

    client.initialize();

    client.on(`qr`, (qr) => {
        console.log('qr', qr);
    });

    client.on(`authenticated`, (session) => {
        if (!fs.existsSync(`./${number}.json`)) {
            fs.writeFile(`./${number}.json`, JSON.stringify(session), function (err) {
                if (err) console.log(err);
                else console.log(`Session stored`);
            });
        }
    });

    client.on(`auth_failure`, (msg) => {
        console.log(`auth_failure`, msg);
    });

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

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

    client.on(`disconnected`, (reason) => {
        console.log(`disconnected`, reason);
    });

};

new session('phone-number-1');
new session('phone-number-2');
new session('phone-number-3');

It would be interesting to implement this script in the examples.

how do you send messages with a particular session?

How i do send message with different route using thats multi session code ?

pedroslopez commented 4 years ago

How i do send message with different route using thats multi session code ?

You will need to store the client in some way, maybe in an object. Using that example, I would return client in that session function, and then save them like this:

const sessions = {
    '1234567890': session('1234567890'),
    '1111123456': session('1111123456')
}

you could then later refer to these like so:

sessions['1234567890'].sendMessage()
asepwaee commented 4 years ago

How i do send message with different route using thats multi session code ?

You will need to store the client in some way, maybe in an object. Using that example, I would return client in that session function, and then save them like this:

const sessions = {
    '1234567890': session('1234567890'),
    '1111123456': session('1111123456')
}

you could then later refer to these like so:

sessions['1234567890'].sendMessage()

i am tryng tu use this method. but i still get the problem and having error. this my session. `var express = require('express') var app = express() const http = require('http'); const url = require('url'); const hostname = '127.0.0.1'; const port = 3000;

const {Client} = require(whatsapp-web.js); const fs = require(fs);

const session = function (number) {

console.log('number', number);

let session_file;
if (fs.existsSync(`./${number}.json`)) {
    session_file = require(`./${number}.json`);
    console.log('session_file', session_file);
}

const client = new Client({
    puppeteer: {
        headless: false,
        userDataDir: __dirname + `/${number}`,
        args: ['--no-sandbox']
    },
    session: session_file
});

client.initialize();

client.on(`qr`, (qr) => {
    console.log('qr', qr);
});

client.on(`authenticated`, (session) => {
    if (!fs.existsSync(`./${number}.json`)) {
        fs.writeFile(`./${number}.json`, JSON.stringify(session), function (err) {
            if (err) console.log(err);
            else console.log(`Session stored`);
        });
    }
});

client.on(`auth_failure`, (msg) => {
    console.log(`auth_failure`, msg);
});

client.on(`ready`, () => {
    console.log(`ready`);

});

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

client.on(`disconnected`, (reason) => {
    console.log(`disconnected`, reason);
});

};

new session('082113150495');

app.get('/send', function (req, res, next) {

    const sessions = {
        '082113150495': session('082113150495')
    }

    sessions['082113150495'].sendMessage("6282286732171@c.us", `test`).then((r) => {
        console.log("sendMessage",r)
    });
    next();

})

app.listen(port, hostname, () => { console.log(Server running at http://${hostname}:${port}/); });`

how do i can send the message inside the router. like this `app.get('/send', function (req, res, next) {

    const sessions = {
        '082113150495': session('082113150495')
    }

    sessions['082113150495'].sendMessage("6282286732171@c.us", `test`).then((r) => {
        console.log("sendMessage",r)
    });
    next();

}) when i execute the route, error like this. TypeError: Cannot read property 'sendMessage' of undefined`

whats is my problem, thanks

pedroslopez commented 4 years ago

@Marzuki5 you need to return the client when creating the session:

const session = function (number) {

    // ...

    return client;
};
asepwaee commented 4 years ago

@pedroslopez

i got new error when execute the /send route.

this my code

`var express = require('express') var app = express() const http = require('http'); const url = require('url'); const hostname = '127.0.0.1'; const port = 3000;

const wa = require('waweb-phi'); const fs = require(fs);

app.get('/scan/:id', function (req, res, next) {

var number = req.params.id ;

const session = function (number) {

console.log('number', number);

let session_file;
if (fs.existsSync(`./${number}.json`)) {
    session_file = require(`./${number}.json`);
    console.log('session_file', session_file);
}

const client = new wa({
    puppeteer: {
        headless: false,
        userDataDir: __dirname + `/${number}`,
        args: ['--no-sandbox']
    },
    session: session_file
});

client.initialize();

client.on(`qr`, (qr) => {
    console.log('qr', qr);
});

client.on(`authenticated`, (session) => {
    if (!fs.existsSync(`./${number}.json`)) {
        fs.writeFile(`./${number}.json`, JSON.stringify(session), function (err) {
            if (err) console.log(err);
            else console.log(`Session stored`);
        });
    }
});

client.on(`auth_failure`, (msg) => {
    console.log(`auth_failure`, msg);
});

client.on(`ready`, () => {
    console.log(`ready`);

});

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

client.on(`disconnected`, (reason) => {
    console.log(`disconnected`, reason);
});

return client;

};

new session('082113150495');

next();

});

app.get('/send', function (req, res, next) { new session('082113150495'); client.sendMessage("6282286732171@c.us", test).then((r) => { console.log("sendMessage",r) }) }); app.listen(port, hostname, () => { console.log(Server running at http://${hostname}:${port}/); });`

dodysat commented 4 years ago

@Marzuki5 I got the same error

iriobf commented 4 years ago
let sessions = {};
const session = function (number) {
    const SESSION_FILE_PATH = __dirname + `/../sessions/session_${number}.json`;

    if (fs.existsSync(SESSION_FILE_PATH)) {
        sessionData = require(SESSION_FILE_PATH);
    }

    const puppeteerOptions = {
        session: sessionData,
        puppeteer: {
            //headless: false,
            userDataDir: __dirname + `/../sessions/${number}`,
            args: ['--no-sandbox', '--disable-setuid-sandbox']
        }
    };

    // Use the saved values
    sessions[number] = new Client(puppeteerOptions);

    sessions[number].initialize();

   // Save session values to the file upon successful auth
    sessions[number].on('authenticated', (session) => {
        sessionData = session;
        fs.writeFile(SESSION_FILE_PATH, JSON.stringify(session), function (err) {
            if (err) console.log(err);
            else console.log(`Session stored`);
        });
    });

    // ...

    return sessions[number];
};
session('1234567890');
let from = '1234567890'
let to = '1212341234'
sessions[from].sendMessage(`55${to}@c.us`, content)
MuhShalah007 commented 3 years ago

https://github.com/pedroslopez/whatsapp-web.js/issues/45#issuecomment-673041886 How to destroy / close session? i got some error like this

(node:9104) UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Target closed.
    at F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\Connection.js:208:63
    at new Promise (<anonymous>)
    at CDPSession.send (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\Connection.js:207:16)
    at ExecutionContext._evaluateInternal (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:200:50)
    at ExecutionContext.evaluateHandle (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:151:21)
    at WaitTask.rerun (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:528:37)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(node:9104) 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(). (rejection id: 1)
(node:9104) [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.
iriobf commented 3 years ago

#45 (comment) How to destroy / close session? i got some error like this

(node:9104) UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Target closed.
    at F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\Connection.js:208:63
    at new Promise (<anonymous>)
    at CDPSession.send (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\Connection.js:207:16)
    at ExecutionContext._evaluateInternal (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:200:50)
    at ExecutionContext.evaluateHandle (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:151:21)
    at WaitTask.rerun (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:528:37)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(node:9104) 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(). (rejection id: 1)
(node:9104) [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.
sessions[number].destroy();
delete sessions[number];
MuhShalah007 commented 3 years ago

#45 (comment) How to destroy / close session? i got some error like this

(node:9104) UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Target closed.
    at F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\Connection.js:208:63
    at new Promise (<anonymous>)
    at CDPSession.send (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\Connection.js:207:16)
    at ExecutionContext._evaluateInternal (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:200:50)
    at ExecutionContext.evaluateHandle (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:151:21)
    at WaitTask.rerun (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:528:37)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(node:9104) 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(). (rejection id: 1)
(node:9104) [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.
sessions[number].destroy();
delete sessions[number];

I got the same error

asepwaee commented 3 years ago
let sessions = {};
const session = function (number) {
    const SESSION_FILE_PATH = __dirname + `/../sessions/session_${number}.json`;

    if (fs.existsSync(SESSION_FILE_PATH)) {
        sessionData = require(SESSION_FILE_PATH);
    }

    const puppeteerOptions = {
        session: sessionData,
        puppeteer: {
            //headless: false,
            userDataDir: __dirname + `/../sessions/${number}`,
            args: ['--no-sandbox', '--disable-setuid-sandbox']
        }
    };

    // Use the saved values
    sessions[number] = new Client(puppeteerOptions);

    sessions[number].initialize();

   // Save session values to the file upon successful auth
    sessions[number].on('authenticated', (session) => {
        sessionData = session;
        fs.writeFile(SESSION_FILE_PATH, JSON.stringify(session), function (err) {
            if (err) console.log(err);
          else console.log(`Session stored`);
        });
    });

    // ...

    return sessions[number];
};
session('1234567890');
let from = '1234567890'
let to = '1212341234'
sessions[from].sendMessage(`55${to}@c.us`, content)

thnks for the answer, its work for me, but i have another problem, when i send messange with that function, my whatsapp messanger going force close. is that a bug ?

vendroid12 commented 3 years ago
let sessions = {};
const session = function (number) {
    const SESSION_FILE_PATH = __dirname + `/../sessions/session_${number}.json`;

    if (fs.existsSync(SESSION_FILE_PATH)) {
        sessionData = require(SESSION_FILE_PATH);
    }

    const puppeteerOptions = {
        session: sessionData,
        puppeteer: {
            //headless: false,
            userDataDir: __dirname + `/../sessions/${number}`,
            args: ['--no-sandbox', '--disable-setuid-sandbox']
        }
    };

    // Use the saved values
    sessions[number] = new Client(puppeteerOptions);

    sessions[number].initialize();

   // Save session values to the file upon successful auth
    sessions[number].on('authenticated', (session) => {
        sessionData = session;
        fs.writeFile(SESSION_FILE_PATH, JSON.stringify(session), function (err) {
            if (err) console.log(err);
            else console.log(`Session stored`);
        });
    });

    // ...

    return sessions[number];
};
session('1234567890');
let from = '1234567890'
let to = '1212341234'
sessions[from].sendMessage(`55${to}@c.us`, content)

thnks for the answer, its work for me, but i have another problem, when i send messange with that function, my whatsapp messanger going force close. is that a bug ?

have you find a work around this issue?

winkcler commented 3 years ago

#45 (comment) How to destroy / close session? i got some error like this

(node:9104) UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Target closed.
    at F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\Connection.js:208:63
    at new Promise (<anonymous>)
    at CDPSession.send (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\Connection.js:207:16)
    at ExecutionContext._evaluateInternal (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:200:50)
    at ExecutionContext.evaluateHandle (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:151:21)
    at WaitTask.rerun (F:\whatsapp-web.js\node_modules\puppeteer\lib\cjs\puppeteer\common\DOMWorld.js:528:37)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(node:9104) 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(). (rejection id: 1)
(node:9104) [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.
sessions[number].destroy();
delete sessions[number];

I got the same error

I'm getting this same problem, has anyone managed to solve it?

winkcler commented 3 years ago

I'm getting this same problem, has anyone managed to solve it?

prashantnirgun commented 3 years ago

for multiple session is there any branch or forked repo, I am new to it not understanding in which file you are making changes does any one has stable version of multiple session please let me know.

MuhammadTaimoor795 commented 2 years ago
let sessions = {};
const session = function (number) {
    const SESSION_FILE_PATH = __dirname + `/../sessions/session_${number}.json`;

    if (fs.existsSync(SESSION_FILE_PATH)) {
        sessionData = require(SESSION_FILE_PATH);
    }

    const puppeteerOptions = {
        session: sessionData,
        puppeteer: {
            //headless: false,
            userDataDir: __dirname + `/../sessions/${number}`,
            args: ['--no-sandbox', '--disable-setuid-sandbox']
        }
    };

    // Use the saved values
    sessions[number] = new Client(puppeteerOptions);

    sessions[number].initialize();

   // Save session values to the file upon successful auth
    sessions[number].on('authenticated', (session) => {
        sessionData = session;
        fs.writeFile(SESSION_FILE_PATH, JSON.stringify(session), function (err) {
            if (err) console.log(err);
          else console.log(`Session stored`);
        });
    });

    // ...

    return sessions[number];
};
session('1234567890');
let from = '1234567890'
let to = '1212341234'
sessions[from].sendMessage(`55${to}@c.us`, content)

not working for me any implement this code ?

jonatanfelipesiqueira commented 2 years ago

Algum exemplo ? os acimas nao funcionou , quando conecto o segundo telefone ele fecha

jonatanfelipesiqueira commented 2 years ago

Acredito que consegui algo , porém o on('authenticate') nao funciona na authLocal, posso continuar a usar sem o on('authenticate')

uthx commented 1 year ago

I was stuck for a couple of hours on handling multiple sessions but thanks to the great community, I found my way around by checking discussions on multiple issues. Posting my solution below.

export const clientSessionStore = {};
console.log(clientSessionStore);
app.post('/initSession/:phone', (req, res) => {
    try {
        const phoneNumber = req.params.phone;
        const clientInstance = sessionManager(phoneNumber);
        clientSessionStore[phoneNumber] = clientInstance
        res.send("positive")
    } catch (error) {
        console.log("initSession error", error);
        res.send("negative");
    }
})

Using the clientSessionStore, for example, sendMessage is called and in the body, we have the message and receiver details and in params, we have the sessionId which in my case is phoneNumber

The first thing that I do inside the sendMessage controller is calling getClientInstance with clientSessionId as input which handles almost everything.

export const getClientInstance = (sessionId) => {
    if(!sessionId) throw new Error(`getClientInstance: Invalid sessionId: ${sessionId}`);
    const client = clientSessionStore[sessionId];
    if(!client) throw new Error(`getClientInstance: No existing session found for clientSessionId : ${sessionId}`);
    return client;
}
ANDRES1102 commented 1 year ago

Estuve atascado durante un par de horas en el manejo de varias sesiones, pero gracias a la gran comunidad, encontré mi camino revisando las discusiones sobre múltiples temas. Publicando mi solución a continuación.

  • Una función que inicia el cliente y mantiene la sesión usando Local Auth como authStrategy.
// import {Client, LocalAuth} from 'whatsapp-web.js';
import WhatsappClient from 'whatsapp-web.js';
import qrCode from 'qrcode-terminal';
export const sessionManager = (sessionId) => {

    const client = new WhatsappClient.Client({
        authStrategy: new WhatsappClient.LocalAuth({
            clientId: sessionId
        })
    })
    client.on('authenticated', () => {
        console.log(`Client: ${sessionId} is Authenticated`);
    });

    client.on('qr', code => {
        console.log(` Generating QE for ${sessionId}`)
        qrCode.generate(code, {small: true})
    });

    client.on('ready', () => {
        console.log(`Client : ${sessionId} is ready.`)
    })
    client.on('message', message => {
        console.log(`Client: ${sessionId} received a mesage`, message.body);
    })
    client.initialize();

    return client
}
  • Almacenar sessionId (para simplificar, en mi caso, es el número de teléfono de los usuarios) como una clave y el objeto de cliente devuelto de la función anterior como un valor.
export const clientSessionStore = {};
console.log(clientSessionStore);
app.post('/initSession/:phone', (req, res) => {
    try {
        const phoneNumber = req.params.phone;
        const clientInstance = sessionManager(phoneNumber);
        clientSessionStore[phoneNumber] = clientInstance
        res.send("positive")
    } catch (error) {
        console.log("initSession error", error);
        res.send("negative");
    }
})

Usando el clientSessionStore, por ejemplo, se llama a sendMessage y en el cuerpo, tenemos los detalles del mensaje y del receptor y en params, tenemos el sessionId que en mi caso es phoneNumber

Lo primero que hago dentro del sendMessagecontrolador es llamar getClientInstancecomo clientSessionIdentrada, que maneja casi todo.

export const getClientInstance = (sessionId) => {
    if(!sessionId) throw new Error(`getClientInstance: Invalid sessionId: ${sessionId}`);
    const client = clientSessionStore[sessionId];
    if(!client) throw new Error(`getClientInstance: No existing session found for clientSessionId : ${sessionId}`);
    return client;
}

This code works perfectly except when sending plain messages. It works for sending lists, buttons, locations, images, etc. It returns a positive response, but in reality, it doesn't send anything. How can you help me? Thank you very much.

Oladapodaniel commented 1 year ago

Hello, this seem to be an old thread, but i have a concern here. With the example above no authStrategy was used, session property was passed though.

But it seems this method of passing session property to the Client is deprecated as i have this error below. (node:3536) DeprecationWarning: options.session is deprecated and will be removed in a future release due to incompatibility with multi-device. Use the LocalAuth authStrategy, don't pass in a session as an option, or suppress this warning by using the LegacySessionAuth strategy explicitly (see https://wwebjs.dev/guide/authentication.html#legacysessionauth-strategy).

How can i use RemothAuth as the authStrategy and also implement it for multiple client? NB. session is undefined in the authenticated event when using RemoteAuth

Any0ne please...

lailamaya2001 commented 1 year ago

Hi, this seems to be an old thread, but I have a concern here. I am doing a small product demo for many users, how can I manage when users send messages because they all use the first user's information to authenticate to send to others My code is as follows mongoose.connect('mongodb://localhost:27017/example_wwebjs') .then(() => {

const store = new MongoStore({ mongoose: mongoose });
const client = new Client({
  puppeteer: {
        headless: true,
        args: [
          '--no-sandbox',
          '--disable-setuid-sandbox',
          '--disable-dev-shm-usage',
          '--disable-accelerated-2d-canvas',
          '--no-first-run',
          '--no-zygote',
          '--single-process', // <- this one doesn't works in Windows
          '--disable-gpu'
        ],
      },
    authStrategy: new RemoteAuth({
        store: store,
        clientId: clientId_run,
        backupSyncIntervalMs: 300000
    })
});

client.initialize().catch(_ => _);

app.post('/sendMessChat',async (req, res) => { console.log("check number"); console.log(req.body.number); let check_resp = await client.sendMessage(req.body.chatID, req.body.text_mess); if (check_resp) { return res.status(200).json("success") } }); io.on("connection", socket => { socket.emit('message_qr', 'Connecting...'); client.on('remote_session_saved', (array) => { console.log("remote_session_saved"); console.log(randomString); socket.emit('remote_session_saved', randomString); }) client.on('qr', (qr) => { // console.log('QR RECEIVED', qr); qrcode.toDataURL(qr, (err, url) => { socket.emit('qr', url); socket.emit('message_qr', 'QR Code received, scan please!'); }); }); client.on('ready',async () => { socket.emit('ready', 'Whatsapp is ready!'); socket.emit('message', 'Whatsapp is ready!');

  var getchats = await client.getChats();

  const result = getchats.map((item) => ({
    chatID: item.id._serialized,
    body: [{message:item.lastMessage ? item.lastMessage.body : '',chatID:item.id._serialized,name: item.name}],
    name: item.name, 
  })); 
  socket.emit('whatsappReady',result); 
});
client.on('message', async msg => { 
   console.log("check msg");
   console.log(msg);
  let data_resp = {
    text_resp:msg.body,
    chatID : msg.from,
  }
  socket.emit('recieve', data_resp);

}); client.on('authenticated',async () => {

  socket.emit('message', 'Whatsapp is authenticated!');
  console.log('AUTHENTICATED');

});

client.on('auth_failure', function(session) {
  socket.emit('message', 'Auth failure, restarting...');
});
client.on('disconnected', (reason) => {
  socket.emit('message', 'Whatsapp is disconnected!');
  client.destroy();
  client.initialize();
});

});

}); hope to get help from everyone thank you

Ashish-bmn commented 1 year ago

The corrected version follows with multiple sessions.

const {Client} = require(`./1.0.1/index`);
const fs = require(`fs`);

const session = function (number) {

    console.log('number', number);

    let session_file;
    if (fs.existsSync(`./${number}.json`)) {
        session_file = require(`./${number}.json`);
        console.log('session_file', session_file);
    }

    const client = new Client({
        puppeteer: {
            headless: false,
            userDataDir: __dirname + `/${number}`,
            args: ['--no-sandbox']
        },
        session: session_file
    });

    client.initialize();

    client.on(`qr`, (qr) => {
        console.log('qr', qr);
    });

    client.on(`authenticated`, (session) => {
        if (!fs.existsSync(`./${number}.json`)) {
            fs.writeFile(`./${number}.json`, JSON.stringify(session), function (err) {
                if (err) console.log(err);
                else console.log(`Session stored`);
            });
        }
    });

    client.on(`auth_failure`, (msg) => {
        console.log(`auth_failure`, msg);
    });

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

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

    client.on(`disconnected`, (reason) => {
        console.log(`disconnected`, reason);
    });

};

new session('phone-number-1');
new session('phone-number-2');
new session('phone-number-3');

It would be interesting to implement this script in the examples.

how do you send messages with a particular session?

(node:1496) DeprecationWarning: options.session is deprecated and will be removed in a future release due to incompatibility with multi-device. Use the LocalAuth authStrategy, don't pass in a session as an option, or suppress this warning by using the LegacySessionAuth strategy explicitly (see https://wwebjs.dev/guide/authentication.html#legacysessionauth-strategy). (Use node --trace-deprecation ... to show where the warning was created)

arbisyarifudin commented 1 year ago

won't this make nodejs open a new chromium. Won't this be a problem when 100 sessions are running simultaneously?

Ant0nioSouza commented 8 months ago

The corrected version follows with multiple sessions.

const {Client} = require(`./1.0.1/index`);
const fs = require(`fs`);

const session = function (number) {

  console.log('number', number);

  let session_file;
  if (fs.existsSync(`./${number}.json`)) {
      session_file = require(`./${number}.json`);
      console.log('session_file', session_file);
  }

  const client = new Client({
      puppeteer: {
          headless: false,
          userDataDir: __dirname + `/${number}`,
          args: ['--no-sandbox']
      },
      session: session_file
  });

  client.initialize();

  client.on(`qr`, (qr) => {
      console.log('qr', qr);
  });

  client.on(`authenticated`, (session) => {
      if (!fs.existsSync(`./${number}.json`)) {
          fs.writeFile(`./${number}.json`, JSON.stringify(session), function (err) {
              if (err) console.log(err);
              else console.log(`Session stored`);
          });
      }
  });

  client.on(`auth_failure`, (msg) => {
      console.log(`auth_failure`, msg);
  });

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

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

  client.on(`disconnected`, (reason) => {
      console.log(`disconnected`, reason);
  });

};

new session('phone-number-1');
new session('phone-number-2');
new session('phone-number-3');

It would be interesting to implement this script in the examples.

Error: Authenticating via JSON session is not supported for MultiDevice-enabled WhatsApp accounts. at LegacySessionAuth.getAuthEventPayload (/home/antonio/Documents/project-x/code/AIPSA/src/main/node/node_modules/whatsapp-web.js/src/authStrategies/LegacySessionAuth.js:57:24) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Client.initialize (/home/antonio/Documents/project-x/code/AIPSA/src/main/node/node_modules/whatsapp-web.js/src/Client.js:474:34)

saadhossain commented 1 month ago

how do you send the numbers to the session? are you adding numbers manually? Is there any way to make an instance by scanning the QR code, like how many accounts scan the code it will make a separate client for each account