Package detail

sulla

danielcardeenas112ISC2.4.0

Javascript whatsapp framework

whatsapp, javascript, bot, typescript

readme

Sulla logo

Sulla

npm version npm type definitions GitHub last commit GitHub license codebeat badge FOSSA Status

Sulla is a javascript library which provides a high-level API control to Whatsapp so it can be configured to automatize resposes or any data that goes trough Whatsapp effortlessly.

It is built using puppeteer and it begin based on this python wrapper

By default sulla will try to use Google Chrome driver if installed, if not, it will use integrated Chromium instance

Changelog:

☑️ Add refreshQR option in create()

☑️ Add openChat() function with UI Layer

☑️ Self check for updates

☑️ More parameters to create()

☑️ Added d.ts types comments for friendlier development

☑️ Fixed video send, fixed optional create() parameters

☑️ Bundle size now just 300 kB

☑️ Added debug option and useChrome to create()

Installation

> npm i sulla

Getting started

// Supports ES6
// import { create, Whatsapp } from 'sulla';
const sulla = require('sulla');

sulla.create().then((client) => start(client));

function start(client) {
  client.onMessage((message) => {
    if (message.body === 'Hi') {
      client.sendText(message.from, '👋 Hello from sulla!');
    }
  });
}

After executing create() function, sulla will create an instance of whatsapp web. If you are not logged in, it will print a QR code in the terminal. Scan it with your phone and you are ready to go!
Sulla will remember the session so there is no need to authenticate everytime.
Multiples sessions can be created at the same time by pasing a session name to create() function:
// Init sales whatsapp bot
sulla.create('sales').then((salesClient) => {...});

// Init support whatsapp bot
sulla.create('support').then((supportClient) => {...});


Optional create parameters

Sulla create() method third parameter can have the following optional parameters:

create('sessionName', qrCallback, {
  headless: true, // Headless chrome
  devtools: false, // Open devtools by default
  useChrome: true, // If false will use Chromium instance
  debug: false, // Opens a debug session
  logQR: true // Logs QR automatically in terminal
  browserArgs: [''] // Parameters to be added into the chrome browser instance
  refreshQR: 15000, // Will refresh QR every 15 seconds, 0 will load QR once. Default is 30 seconds
});
The type definition con be found in here: CreateConfig.ts

Exporting QR code

By default QR code will appear on the terminal. If you need to pass the QR somewhere else heres how:

const fs = require('fs');

// Second create() parameter is the QR callback
sulla.create('session-marketing', (base64Qr, asciiQR) => {
  // To log the QR in the terminal
  console.log(asciiQR);

  // To write it somewhere else in a file
  exportQR(base64Qr, 'marketing-qr.png');
});

// Writes QR in specified path
function exportQR(qrCode, path) {
  qrCode = qrCode.replace('data:image/png;base64,', '');
  const imageBuffer = Buffer.from(qrCode, 'base64');

  // Creates 'marketing-qr.png' file
  fs.writeFileSync(path, imageBuffer);
}

Downloading files

Puppeteer takes care of the file downloading. The decryption is being done as fast as possible (outruns native methods). Supports big files!

import fs = require('fs');
import mime = require('mime-types');

client.onMessage(async (message) => {
  if (message.isMedia) {
    const buffer = await client.downloadFile(message);
    // At this point you can do whatever you want with the buffer
    // Most likely you want to write it into a file
    const fileName = `some-file-name.${mime.extension(message.mimetype)}`;
    fs.writeFile(fileName, buffer, function (err) {
      ...
    });
  }
});

Basic functions (usage)

Not every available function is listed, for further look, every function available can be found in here and here

Chatting

Here, chatId could be <phoneNuber>@c.us or <phoneNumber>-<groupId>@c.us
// Send basic text
await client.sendText(chatId, '👋 Hello from sulla!');

// Send image
await client.sendImage(
  chatId,
  'path/to/img.jpg',
  'image-name.jpg',
  'Caption text'
);

// Send @tagged message
await client.sendMentioned(chatId, 'Hello @5218113130740 and @5218243160777!', [
  '5218113130740',
  '5218243160777',
]);

// Reply to a message
await client.reply(chatId, 'This is a reply!', message.id.toString());

// Send file (sulla will take care of mime types, just need the path)
await client.sendFile(chatId, 'path/to/file.pdf', 'cv.pdf', 'Curriculum');

// Send gif
await client.sendVideoAsGif(
  chatId,
  'path/to/video.mp4',
  'video.gif',
  'Gif image file'
);

// Send contact
// contactId: 52155334634@c.us
await client.sendContact(chatId, contactId);

// Forwards messages
await client.forwardMessages(chatId, [message.id.toString()], true);

// Send sticker
await client.sendImageAsSticker(chatId, 'path/to/image.jpg');

// Send location
await client.sendLocation(
  chatId,
  25.6801987,
  -100.4060626,
  'Some address, Washington DC',
  'Subtitle'
);

// Send seen ✔️✔️
await client.sendSeen(chatId);

// Start typing...
await client.startTyping(chatId);

// Stop typing
await client.stopTyping(chatId);

// Set chat state (0: Typing, 1: Recording, 2: Paused)
await client.setChatState(chatId, 0 | 1 | 2);

Retrieving data

// Retrieve contacts
const contacts = await client.getAllContacts();

// Retrieve all messages in chat
const allMessages = await client.loadAndGetAllMessagesInChat(chatId);

// Retrieve contact status
const status = await client.getStatus(contactId);

// Retrieve user profile
const user = await client.getNumberProfile(contactId);

// Retrieve all unread message
const messages = await client.getAllUnreadMessages();

// Retrieve all chats
const chats = await client.getAllChats();

// Retrieve all groups
const chats = await client.getAllGroups();

// Retrieve profile fic (as url)
const url = await client.getProfilePicFromServer(chatId);

// Retrieve chat/conversation
const chat = await client.getChat(chatId);

Group functions

// groupId or chatId: leaveGroup 52123123-323235@g.us

// Leave group
await client.leaveGroup(groupId);

// Get group members
await client.getGroupMembers(groupId);

// Get group members ids
await client.getGroupMembersIds(groupId);

// Generate group invite url link
await client.getGroupInviteLink(groupId);

// Create group (title, participants to add)
await client.createGroup('Group name', ['123123@c.us', '45456456@c.us']);

// Remove participant
await client.removeParticipant(groupId, '123123@c.us');

// Add participant
await client.addParticipant(groupId, '123123@c.us');

// Promote participant (Give admin privileges)
await client.promoteParticipant(groupId, '123123@c.us');

// Demote particiapnt (Revoke admin privileges)
await client.demoteParticipant(groupId, '123123@c.us');

// Get group admins
await client.getGroupAdmins(groupId);

Profile functions

// Set client status
await client.setProfileStatus('On vacations! ✈️');

// Set client profile name
await client.setProfileName('Sulla bot');

Device functions

// Get device info
await client.getHostDevice();

// Get connection state
await client.getConnectionState();

// Get battery level
await client.getBatteryLevel();

// Is connected
await client.isConnected();

// Get whatsapp web version
await client.getWAVersion();

Events

// Listen to messages
client.onMessage(message => {
  ...
})

// Listen to state changes
client.onStateChange(state => {
  ...
});

// Listen to ack's
client.onAck(ack => {
  ...
});

// Listen to live location
// chatId: 'phone@c.us'
client.onLiveLocation(chatId, (liveLocation) => {
  ...
});

// chatId looks like this: '5518156745634-1516512045@g.us'
// Event interface is in here: https://github.com/danielcardeenas/sulla/blob/master/src/api/model/participant-event.ts
client.onParticipantsChanged(chatId, (event) => {
  ...
});

// Listen when client has been added to a group
client.onAddedToGroup(chatEvent => {
  ...
});

Other

// Delete chat
await client.deleteChat(chatId);

// Clear chat messages
await client.clearChat(chatId);

// Delete message (last parameter: delete only locally)
await client.deleteMessage(chatId, message.id.toString(), false);

// Retrieve a number profile / check if contact is a valid whatsapp number
const profile = await client.getNumberProfile('0000000@c.us');

Misc

There are some tricks for a better usage of sulla.

Keep session alive:

// In case of being logged out of whatsapp web
// Force it to keep the current session
// State change
client.onStateChange((state) => {
  console.log(state);
  const conflits = [
    sulla.SocketState.CONFLICT,
    sulla.SocketState.UNPAIRED,
    sulla.SocketState.UNLAUNCHED,
  ];
  if (conflits.includes(state)) {
    client.useHere();
  }
});

Send message to new contacts (non-added)

Also see Whatsapp links Be careful since this can pretty much could cause a ban from Whatsapp, always keep your contacts updated!

await client.sendMessageToId('5212234234@c.us', 'Hello from sulla! 👋');

Multiple sessions

If you need to run multiple sessions at once just pass a session name to create() method.

async () => {
  const marketingClient = await sulla.create('marketing');
  const salesClient = await sulla.create('sales');
  const supportClient = await sulla.create('support');
};

Closing (saving) sessions

Close the session properly to ensure the session is saved for the next time you log in (So it wont ask for QR scan again). So instead of CTRL+C,

// Catch ctrl+C
process.on('SIGINT', function() {
  client.close();
});

// Try-catch close
try {
   ...
} catch (error) {
   client.close();
}

Debugging

Development

Building sulla is really simple altough it contians 3 main projects inside

  1. Wapi project
> npm run build:wapi
  1. Middleeware
> npm run build:build:middleware
> npm run build:jsQR
  1. Sulla
> npm run build:sulla

To build the entire project just run

> npm run build

Sulla state

As of version 2.3.5 it seems that sulla has reached a very rich and stable functionality and architecture. As much as I would love to, I cannot dedicate a lot of time to this project so please consider checking out forked versions of sulla where other developers can dedicate more time and support to it.

Maintainers

Maintainers are needed, I cannot keep with all the updates by myself. If you are interested please open a Pull Request.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

License

FOSSA Status

changelog

Changelog

All notable changes to this project will be documented in this file. Dates are displayed in UTC.

Generated by auto-changelog.

v2.3.14

13 April 2020

2.3.10

10 April 2020

  • feat: Added args property to initialization options for customizing arguments passed to browser instance #240
  • Restyle Add license scan report and status #247
  • feat: Added args property to initialization options for customizing arguments passed to browser instance #240
  • docs support 2623605
  • Restyled by jq 5dbd783
  • Restyled by clang-format a584006
  • release-it and auto-changelog generation 2930844
  • Add release-it 01acb4c
  • Fix spinner mistake f8c35cd
  • Bump nodemon from 2.0.2 to 2.0.3 d806028
  • Selfcheck for updates ee95f72
  • Selfcheck for updates 31832eb
  • Restyled by whitespace 7c722d1
  • Add retrievers, deprecate some unneeded functions d41bb44
  • Better logging, extract QR as ascii 1a77f6b
  • Better logging, extract QR as ascii 4db4419
  • Fix video sending, fix optional parameters on create 3c85195
  • Fix spinner mistake 5643071
  • Bump husky from 4.2.4 to 4.2.5 757afb0
  • Add browserArgs to readme.md e124a19
  • Add browserArgs to readme.md ca5f4bf
  • Add cmd user interaction 7eba90c
  • Update README.md d4a5a19
  • Update README.md 7638884
  • Add updates.md 6c68705
  • Add updates.md a611cd9
  • Fix spinner mistake c23e7b4
  • Update codebeat and gitignore 092d608
  • Update README.md 5c798d7
  • Bump @types/node from 13.11.0 to 13.11.1 24b25ee
  • Update UPDATES.md 00ebd9e
  • Update README.md 5ac0b37
  • Update README.md ba5ae7f
  • Update README.md 186a537
  • Update README.md b5ca860
  • Wrong options reference my bad! dd67081
  • fix codebeatignore docs folder 58a4f62
  • Bump version b35cc77
  • Update README.md 267ec1f
  • add docs to codebeatignore 95ee67e
  • added missing SocketState to exports fc4e3e9

2.3.5

7 April 2020

  • 345.0 kB Bundle size, Add create options 65deefe

2.3.4

7 April 2020

  • Adds useChrome parameter, adds debug url, updates UA #232
  • Update npmignore 97dd502
  • Update .gitignore bb30d9a

2.3.3

7 April 2020

  • (Restyle) Debug URL in initializer #231
  • Bump prettier from 2.0.2 to 2.0.4 #226
  • Change UA, add useChrome option, add debug option c3883e2
  • Debug URL in initializer f508180
  • Update README.md 47b68e4
  • Update README.md 890bedb
  • Exclude test file from dist 5303914
  • Restyled by whitespace e255f3a
  • Update README.md aad079f

2.3.2

7 April 2020

2.3.1

6 April 2020

2.2.1

4 April 2020

2.1.1

4 April 2020

2.1.0

4 April 2020

2.0.1

4 April 2020

  • Bump rxjs from 6.5.4 to 6.5.5 #219
  • Bump acorn from 6.4.0 to 6.4.1 #210
  • Add enums from whatsapp definitions 36133a2
  • Use here detection 76683b6
  • Update package.json 8ce1d7b
  • Splitting functions in whatsapp class 6ee66e1
  • Fix merge conflicts f05bddb
  • Add more modular functions to wapi bf7e60b
  • Finish release 7173c8f
  • Fix package-lock.json 7c3bbe8
  • Try to use chrome, fallback to chromium 8f5bb67
  • Add headless and devtools as parameters 3db13a7
  • Expose everything needed to develop b14bc2b
  • Update README.md 8f73b0f
  • Bumb version c14f27e
  • Move to assets 0bae014

2.0.0

3 April 2020

1.1.3

24 January 2020

1.1.2

23 January 2020

  • Bump typescript from 3.6.3 to 3.7.3 #157
  • Bump @types/node from 12.7.5 to 12.12.18 #165
  • [Security] Bump https-proxy-agent from 2.2.2 to 2.2.4 #144
  • Bump husky from 3.0.5 to 3.0.8 #101
  • Bump @types/puppeteer from 1.19.1 to 1.20.1 #105
  • Update ora to the latest version 🚀 #90
  • Bump typescript from 3.6.2 to 3.6.3 #84
  • Bump @types/node from 12.7.4 to 12.7.5 #83
  • Bump puppeteer from 1.19.0 to 1.20.0 #86
  • Bump tsc-watch from 2.4.0 to 4.0.0 #88
  • Bump ts-node from 8.3.0 to 8.4.1 #87
  • Bump rxjs from 6.5.2 to 6.5.3 #77
  • Greenkeeper/@types/puppeteer 1.19.1 #76
  • Greenkeeper/husky 3.0.5 #75
  • Greenkeeper/@types/node 12.7.4 #74
  • Bump husky from 3.0.3 to 3.0.5 #73
  • Bump typescript from 3.5.3 to 3.6.2 #71
  • Bump @types/puppeteer from 1.19.0 to 1.19.1 #60
  • Bump @types/node from 12.7.1 to 12.7.3 #72
  • Bump @types/node from 12.7.0 to 12.7.1 #57
  • Bump husky from 3.0.2 to 3.0.3 #56
  • Fixed typo in README #58
  • Greenkeeper/@types/node 12.7.0 #55
  • Bump @types/node from 12.6.9 to 12.7.0 #53
  • Greenkeeper/tsc watch 2.4.0 #52
  • Bump tsc-watch from 2.2.1 to 2.4.0 #51
  • Bump @types/node from 12.6.8 to 12.6.9 #46
  • Greenkeeper/husky 3.0.2 #45
  • Bump husky from 3.0.1 to 3.0.2 #44
  • Greenkeeper/@types/puppeteer 1.19.0 #42
  • Greenkeeper/puppeteer 1.19.0 #41
  • Bump puppeteer from 1.18.1 to 1.19.0 #39
  • Greenkeeper/husky 3.0.1 #37
  • Greenkeeper/@types/node 12.6.8 #36
  • Bump @types/node from 12.6.3 to 12.6.6 #35
  • Greenkeeper/@types/node 12.6.3 #34
  • Bump @types/node from 12.6.2 to 12.6.3 #33
  • Greenkeeper/@types/node 12.6.2 #31
  • Bump @types/node from 12.6.1 to 12.6.2 #30
  • Bump typescript from 3.5.2 to 3.5.3 #28
  • Bump @types/node from 12.0.12 to 12.6.1 #29
  • Greenkeeper/@types/node 12.0.12 #24
  • Greenkeeper/puppeteer 1.18.1 #22
  • Update husky to the latest version 🚀 #21
  • Bump puppeteer from 1.18.0 to 1.18.1 #18
  • Bump husky from 2.5.0 to 2.7.0 #20
  • Greenkeeper/husky 2.5.0 #14
  • Greenkeeper/@types/node 12.0.10 #15
  • Greenkeeper/puppeteer 1.18.0 #17
  • Bump @types/node from 12.0.8 to 12.0.10 #12
  • Bump husky from 2.4.1 to 2.5.0 #11
  • Bump puppeteer from 1.17.0 to 1.18.0 #10
  • Greenkeeper/ts node 8.3.0 #8
  • Bump typescript from 3.5.1 to 3.5.2 #7
  • Create LICENSE #5
  • Greenkeeper/husky 2.4.1 #3
  • Greenkeeper/@types/node 12.0.8 #4
  • Fix qr code auth ac285d8
  • chore(package): update lockfile package-lock.json f319046
  • chore(package): update lockfile package-lock.json 5451696
  • Fix message receiving 75b3078
  • chore(package): update lockfile package-lock.json 7096ae8
  • chore(package): update lockfile package-lock.json d608075
  • chore(package): update lockfile package-lock.json 5592deb
  • chore(package): update lockfile package-lock.json 2725565
  • Remove note, use own version now 198fb04
  • chore(package): update lockfile package-lock.json 6c56ea4
  • Bundle ready 062ba21
  • Add send contact function 90da04e
  • Add available functions list 24664f9
  • chore(package): update lockfile package-lock.json ea4ef6a
  • Update README.md 2bfe320
  • chore(package): update lockfile package-lock.json 5598b84
  • chore(package): update lockfile package-lock.json cc53cbd
  • Be headless bc82ec2
  • chore(package): update lockfile package-lock.json 1ce271c
  • chore(package): update lockfile package-lock.json 58af3b8
  • chore(package): update lockfile package-lock.json 9527e04
  • chore(package): update lockfile package-lock.json c079623
  • chore(package): update lockfile package-lock.json 30693f1
  • chore(package): update lockfile package-lock.json 6f3af1e
  • chore(package): update lockfile package-lock.json d162b58
  • chore(package): update lockfile package-lock.json 6efaac7
  • chore(package): update lockfile package-lock.json 2d8d89a
  • chore(package): update lockfile package-lock.json 69eb3aa
  • chore(package): update lockfile package-lock.json 09b0103
  • chore(package): update lockfile package-lock.json 732e0ab
  • Update README.md d78a4cb
  • chore(package): update @types/node to version 12.6.3 20e566d
  • chore(package): update husky to version 3.0.5 81518a0
  • chore(package): update @types/node to version 12.6.2 5fefd31
  • chore(package): update husky to version 3.0.2 b1279a8
  • chore(package): update @types/node to version 12.0.12 01d217e
  • Bumb version 4b92f25
  • chore(package): update husky to version 3.0.0 82cb8bd
  • chore(package): update @types/puppeteer to version 1.19.0 e98df6c
  • chore(package): update puppeteer to version 1.18.1 65e596b
  • chore(package): update @types/puppeteer to version 1.19.1 d3e5d54
  • chore(package): update husky to version 2.5.0 378d811
  • chore(package): update @types/node to version 12.7.4 b03b0d0
  • chore(package): update @types/node to version 12.0.10 5c60b3b
  • chore(package): update puppeteer to version 1.19.0 76d210a
  • chore(package): update puppeteer to version 1.18.0 1491dbc
  • chore(package): update @types/node to version 12.7.0 590ccce
  • chore(package): update ts-node to version 8.3.0 06f7fe8
  • chore(package): update husky to version 3.0.1 17b7e18
  • fix(package): update ora to version 4.0.0 d759aa9
  • chore(package): update husky to version 2.4.1 82ee79d
  • chore(package): update @types/node to version 12.6.8 b32df09
  • chore(package): update @types/node to version 12.0.8 28e6579
  • chore(package): update tsc-watch to version 2.4.0 367084d
  • Setup to continue dev 07b9390
  • Update README.md ede96f0

v1.1.1

13 April 2020

1.1.1

10 June 2019

  • Patch release fd67541
  • Setup to continue development of next version ed63ad6

1.1.0

10 June 2019

1.0.3

10 June 2019

1.0.1

10 June 2019