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

Feat/sticker #479

Merged
merged 18 commits into from
Dec 25, 2020
Merged

Feat/sticker #479

merged 18 commits into from
Dec 25, 2020

Conversation

mpirescarvalho
Copy link
Contributor

@mpirescarvalho mpirescarvalho commented Dec 11, 2020

First, good job with the project!
This PR adds the possibility to send WEBP images as stickers.

That's how you would send stickers:

const webpBase64Data = 'UklGRlxWAABXRUJQVlA4WAoAAAAQAAAAgAMAFgIAQUxQSFQ0AAAB...';

client.on('message', async msg => {
    if (msg.body.startsWith('dp!sticker')) {
        const stickerMedia = new MessageMedia('image/webp', webpBase64Data, 'image.webp' );
        client.sendImageAsSticker(msg.from, stickerMedia);
    }
});

It's also possible to send using chat objects:

const chat = await msg.getChat();
const stickerMedia = new MessageMedia('image/webp', webpBase64Data, 'image.webp' );
chat.sendImageAsSticker(stickerMedia)

You could also load the image from file just like normal images:

const stickerMedia = MessageMedia.fromFilePath('./image.webp');

IMAGES HAS TO BE IN WEBP FORMAT FOR THE STICKERS TO BE SENT PROPERLY

That's the result:

This was referenced Dec 14, 2020
return await window.WWebJS.sendSticker(stickerInfo, chatId);
};

window.WWebJS.sendSticker = async function (stickerInfo, chatId) {
Copy link
Collaborator

@aliyss aliyss Dec 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rename this to sendStickerRaw, as there still is potential to add a sendSticker via Sticker Packs which is not yet included in this PR.

// Keep in mind: This is merely a suggestion and maybe @pedroslopez will accept as is.

@aliyss
Copy link
Collaborator

aliyss commented Dec 15, 2020

@mpirescarvalho

Also I found some functions that could help retrieve Information on already added Stickers if you want to add that as well:

Retrieve StickerPacks from phone:

Store.StickerPack.sync()

Check if StickerPacks are fetched from phone:

Store.StickerPack.hasFetchedData()

Retrieve Stickers from StickerPack:

Store.StickerPack.models[0].stickers.fetch()

Sticker Info:

Store.StickerPack.models[0].stickers.models[0]

Reset StickerPacks

Store.StickerPack.reset()

Reset Stickers from StickerPack:

Store.StickerPack.models[0].stickers.reset()

@mpirescarvalho
Copy link
Contributor Author

mpirescarvalho commented Dec 16, 2020

@aliyss

Cool, I'd really apreciate if you can add that

Store.StickerPack.hasFetchedData() may also be useful to check if stickers have been fetched instead of fetching them every time a sticker is sent

Also, after using it for a while, I think sendImageAsSticker should also be renamed, as it is also possible to use it to send gifs or short videos converted to webp format (maybe sendMediaAsSticker ?). In fact the only requirements is that media has to be in WEBP format and be less than 1MB in size

Another thing is that I think client.sendImageAsSticker (or whatever the renamed name will be) should be able to send any image format. For that we would need to convert it internally, but it would require the use of external libs, and I don't know what @pedroslopez thinks about it. If he's positive I can work on it, because I’ve already implemented it in my bot

@aliyss
Copy link
Collaborator

aliyss commented Dec 16, 2020

@mpirescarvalho

I'm currently short on time. So I doubt I will be able to implement it soon enough on my own.

Concerning the internal conversion: I see the added value of converting images internally, however I believe it should only be done if it's via WhatsApp. I assume, that WhatsApp has their own conversion tool integrated somewhere within their code. Or at least hope so.

@pedroslopez
Copy link
Owner

pedroslopez commented Dec 16, 2020

Thanks for contributing!

I haven't yet had the chance to look over this properly, but just seeing it very quickly I see stickers are sent using a new function client.sendImageAsSticker(). To keep things consistent, I would prefer to send these messages in the same way other messages are sent, using client.sendMessage(). It could possibly be an option when creating the MessageMedia or an option on the sendMessage() function, like we did with sendAudioAsVoice: true (although, I think maybe MessageMedia would be a better place for it), or even creating a new model for stickers. These are just proposed solutions, but I'm open to ideas.

Again, I haven't yet looked into the implementation, so let me know your thoughts.

@mpirescarvalho
Copy link
Contributor Author

mpirescarvalho commented Dec 16, 2020

@aliyss,
I don't think whatsapp has their own conversion tool because you can't send new stickers through whatsapp web in normal use, you can only send stickers you have imported in android/ios app first... and it seems that this constraint of media being WEBP just happens in stickers.

@mpirescarvalho
Copy link
Contributor Author

mpirescarvalho commented Dec 16, 2020

@pedroslopez,
I would rather prefer using something like sendMediaAsSticker: true to keep options consistent with sendAudioAsVoice, but sending stickers is done by a different aproach of that used when sending messages. Of course we could just use a if inside sendMessage() and use the send sticker logic when sendMediaAsSticker === true, but sending sticker also doesn't return the message that was sent, like client.sendMessage() does.

Let me know if even then you want me to join this on sendMessage().

What about internal conversion so that it could handle formats other than webp?

@esteves67
Copy link

@mpirescarvalho Thank you so much for implementing the send sticker function 😄 👍

@pedroslopez
Copy link
Owner

@pedroslopez,
I would rather prefer using something like sendMediaAsSticker: true to keep options consistent with sendAudioAsVoice, but sending stickers is done by a different aproach of that used when sending messages. Of course we could just use a if inside sendMessage() and use the send sticker logic when sendMediaAsSticker === true, but sending sticker also doesn't return the message that was sent, like client.sendMessage() does.

Yeah, sendMediaAsSticker seems good to me- in this case I think it would be ok to internally convert images to their required format automatically as you mentioned.

However, if we're sending messages using the regular sendMessage function, it should return the sent message. Is there a way you could manually assign a message ID to the sticker message? What I did to be able to return sent messages was basically rewrite the internal function that created the message and manually generate a new ID for it.

@mpirescarvalho
Copy link
Contributor Author

Ok, so a lots of things have changed here.

Sending Sticker

First, initial functions client.sendImageAsSticker(msg.from, stickerMedia); does not exist anymore.
As @pedroslopez requested, sending stickers is now merged into client.sendMessage() functions. That means it's now possible to send stickers from other functions like msg.reply() or chat.sendMessage().

Usage example:

const webpBase64Data = 'UklGRlxWAABXRUJQVlA4WAoAAAAQAAAAgAMAFgIAQUxQSFQ0AAAB...';

client.on('message', async msg => {
    if (msg.body.startsWith('dp!sticker')) {
        const stickerMedia = new MessageMedia('image/webp', webpBase64Data );
        client.sendMessage(msg.from, stickerMedia, { sendMediaAsSticker: true });
    }
});

Media format

Media format constraint also doesn't exists anymore (images are converted internally), so it's now possible to send any image format like jpeg to the function. You can do:

const stickerMedia = MessageMedia.fromFilePath('imagem.jpg');
client.sendMessage(msg.from, stickerMedia, { sendMediaAsSticker: true });

Videos

You can also send any videos format as stickers (though I only tested it with mp4). You should keep in mind that whatsapp stickers max size is 1MB, so anything bigger than that will not be sent, resulting in a error.

Important:
If you send a video as sticker that is not in webp format, it will try to automaticaly convert it. You need to make sure you have ffmpeg installed for this to work. Also, if you need, you can pass the ffmpeg path while instantiating whatsapp-web.js client:

const client = new Client({
    ...
    ffmpegPath: 'path/to/ffmpeg'
});

@pedroslopez
Copy link
Owner

This is great! That's exactly the way I would have hoped to implement it and it's integrated nicely.
However, the functionality doesn't seem to be working.

Trying to send stickers, it gets stuck pending:
image

I tried with a random image I had, as well as trying to send back a sticker that is already in WhatsApp.

@mpirescarvalho
Copy link
Contributor Author

This is great! That's exactly the way I would have hoped to implement it and it's integrated nicely.
However, the functionality doesn't seem to be working.

Trying to send stickers, it gets stuck pending:
image

I tried with a random image I had, as well as trying to send back a sticker that is already in WhatsApp.

Are you getting any error message? It works nice for me:

client.on('message', async msg => {
    const webpImage = MessageMedia.fromFilePath('image.webp');
    const jpgImage = MessageMedia.fromFilePath('image.jpg');
    const receivedImage = await msg.downloadMedia();

    client.sendMessage(msg.from, webpImage, { sendMediaAsSticker: true });
    client.sendMessage(msg.from, jpgImage, { sendMediaAsSticker: true });
    client.sendMessage(msg.from, receivedImage, { sendMediaAsSticker: true });
});

image

@pedroslopez

This comment has been minimized.

@pedroslopez
Copy link
Owner

pedroslopez commented Dec 21, 2020

Disregard my previous message, the issue I mentioned seems to be unrelated and happens even without sending any stickers with the library.
So no, no issue in the console. Stickers just get stuck in a pending state.

Could more data be missing from the message? I know stickers have some information like sticker name and pack name, but I don't see those being set anywhere.

@mpirescarvalho
Copy link
Contributor Author

Disregard my previous message, the issue I mentioned seems to be unrelated and happens even without sending any stickers with the library.
So no, no issue in the console. Stickers just get stuck in a pending state.

Could more data be missing from the message? I know stickers have some information like sticker name and pack name, but I don't see those being set anywhere.

Yes they have aditional information but those seems to be optional. I'm using this branch on my bot (it allows users to send images and the bot creates a sticker from it) from a week and I haven't had any problems at all.

I think we need anyone else to test it, maybe I'm missing something too.

@esteves67
Copy link

esteves67 commented Dec 21, 2020

@mpirescarvalho @pedroslopez
Im having no problem with mpirescarvalho sticker branch, here it is working perfect.

@mpirescarvalho again, thanks for implementing the sticker function, it will be so much useful for me, and many others!

image
image

@pedroslopez
Copy link
Owner

Alright, the issue I was having was due to the size property not being set. This caused an issue on iOS with both sending and receiving stickers sent by the library.

I just need to test out the animated sticker portion, which I'll get to most likely tomorrow.

@pedroslopez pedroslopez changed the base branch from master to dev December 25, 2020 22:02
Copy link
Owner

@pedroslopez pedroslopez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@pedroslopez pedroslopez merged commit ff7586a into pedroslopez:dev Dec 25, 2020
This was linked to issues Dec 25, 2020
pedroslopez added a commit that referenced this pull request Dec 29, 2020
Adds the option `sendMediaAsSticker` that will take care of converting media to appropriate formats and send it as a sticker. Note that ffmpeg is required to properly convert animated stickers that are not in webp format.

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
tianvier added a commit to tianvier/whatsapp-web.js that referenced this pull request Dec 31, 2020
* 'master' of https://github.com/pedroslopez/whatsapp-web.js:
  chore: mark version v1.12.0
  docs: switch links to point to the guide
  docs: fix error generating Label docs
  feat: Get message delivery information (close pedroslopez#418)
  feat: mark chat as unread (pedroslopez#475)
  feat: add GroupChat types (pedroslopez#485)
  docs: fix typo
  feat: added starred indicator to messages (pedroslopez#501)
  feat: star/unstar messages (pedroslopez#494)
  feat: get Contact's "About" text (close pedroslopez#491)
  feat: get links included in message (pedroslopez#457)
  feat: send media as stickers (pedroslopez#479)
  docs: fix slight typo
  feat: send media as document (pedroslopez#490)
  feat: Get registered ID for a given phone number (pedroslopez#483)
  feat(interface): Open chat search, open chat at message position (pedroslopez#447)
  feat: WA Business Labels support (pedroslopez#407)

# Conflicts:
#	package.json
@mpirescarvalho mpirescarvalho deleted the feat/sticker branch January 12, 2021 14:17
Belfio pushed a commit to Belfio/whatsapp-web.js that referenced this pull request Jan 9, 2024
Adds the option `sendMediaAsSticker` that will take care of converting media to appropriate formats and send it as a sticker. Note that ffmpeg is required to properly convert animated stickers that are not in webp format.

Co-authored-by: Pedro S. Lopez <pedroslopez@me.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Sending A Sticker Send Sticker
4 participants