hoehermann / purple-gowhatsapp

Pidgin/libpurple plug-in for WhatsApp Web.
GNU General Public License v3.0
288 stars 34 forks source link

Improve compatibility with spectrum2 #5

Open evgenyh opened 5 years ago

evgenyh commented 5 years ago

trying to get this plugin to work with spectrum2 libpurple backend

  1. I was able to compile it
  2. spectrum2 able to talk to this plugin.
  3. on attempt to add account I only getting following message in chat window and in logs : "error during login: qr code scan timed out"

P.S> maybe I'm doing something wrong. thanks

piece from log :

8904: 2019-03-27 14:27:22,490 INFO  libpurple: account:Connecting to account ---number-filtered@s.whatsapp.net.
8904: 2019-03-27 14:27:22,490 INFO  libpurple: connection:Connecting. gc = 0x23eb0c0
8904: 2019-03-27 14:27:23,751 INFO  libpurple: gowhatsapp:Recieved: at 0 id  remote login@s.whatsapp.net sender  (fromMe 0)
8904: 2019-03-27 14:27:23,752 INFO  backend: conv_write_im()
8904: 2019-03-27 14:27:23,752 INFO  backend: conv_write_im(): ignoring a system message
...
8953: 2019-03-27 14:28:25,752 INFO  libpurple: gowhatsapp:Recieved: at 0 id (null) remote (null) sender (null) (fromMe 0)
8953: 2019-03-27 14:28:25,752 INFO  libpurple: connection:Connection error on 0x181f0c0 (reason: 0 description: error during login: qr code scan timed out

thanks

hoehermann commented 5 years ago

Nice.

The QR code is supposed to be shown as an image within an instant message flagged as a system message. It looks like system messages are ignored in your set-up. Can you configure spectrum2 to consider all messages? Alternatively, try to change libgowhatsapp.c, line 135 from

    flags |= PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG;

to

    flags |= PURPLE_MESSAGE_NO_LOG;

.

evgenyh commented 5 years ago

yep. that is what I thought . according to spectrum code : https://github.com/SpectrumIM/spectrum2/blob/0076bda7b5040d69f7d8afaf5bdf3db596202f5a/backends/libpurple/main.cpp#L1506

//Ignore system messages as those are normally not true messages in the XMPP sense
        if (flags & PURPLE_MESSAGE_SYSTEM) {
            LOG4CXX_DEBUG(logger, "conv_write_im(): ignoring a system message");
            return;
}

this is not configurable, and changing it will have system wide effect. I'll try to change purple-gowhatsapp code as you suggest

evgenyh commented 5 years ago

changed line you suggested

now i getting these messages :

20445: 2019-03-27 17:30:11,792 INFO  backend: Creating account with name '---number-here-removed-by-me@s.whatsapp.net' and protocol 'prpl-hehoe-gowhatsapp'
20445: 2019-03-27 17:30:11,792 INFO  libpurple: account:Connecting to account 972548048749@s.whatsapp.net.
20445: 2019-03-27 17:30:11,792 INFO  libpurple: connection:Connecting. gc = 0x1a440c0
20445: 2019-03-27 17:30:12,752 INFO  libpurple: gowhatsapp:Recieved: at 0 id  remote login@s.whatsapp.net sender  (fromMe 0)
20445: 2019-03-27 17:30:12,752 INFO  backend: conv_write_im()
20445: 2019-03-27 17:30:12,752 ERROR backend: GLib g_string_free: assertion 'string != NULL' failed
20445: 2019-03-27 17:30:12,752 INFO  backend: Received message body='Scan this QR code within 20 seconds to log in.' xhtml='' name='login@s.whatsapp.net'

and still no qr shown.

getting these messages in client as follows : image

evgenyh commented 5 years ago

just to ensure , that this is not due to some client side limitations of displaying messages, below is a dump of incoming traffic :

<message from="login\40s.whatsapp.net@whatsapp.im.domain/bot" type="chat" to="***masked***@im.domain">
<body>Scan this QR code within 20 seconds to log in.</body>
</message>

<r xmlns="urn:xmpp:sm:3"/>

<message from="login\40s.whatsapp.net@whatsapp.im.domain/bot" type="chat" to="***masked***@im.domain">
<body>Scan this QR code within 20 seconds to log in.</body>
</message>

<r xmlns="urn:xmpp:sm:3"/>

<a xmlns="urn:xmpp:sm:3" h="135"/>

<a xmlns="urn:xmpp:sm:3" h="75"/>

<message from="login\40s.whatsapp.net@whatsapp.im.domain/bot" type="chat" to="***masked***@im.domain">
<body>Scan this QR code within 20 seconds to log in.</body>
</message>

<r xmlns="urn:xmpp:sm:3"/>

<message from="whatsapp.im.domain" type="chat" to="***masked***@im.domain">
<body>error during login: qr code scan timed out
</body>
<spectrumerror xmlns="http://spectrum.im/error" error="0">CONNECTION_ERROR_NETWORK_ERROR</spectrumerror>
</message>

<presence from="whatsapp.im.domain" type="unavailable" to="***masked***@im.domain"/>

thanks

EionRobb commented 5 years ago

spectrum2 has.... issues with inline images. Try adding the PURPLE_MESSAGE_IMAGE flag (might be plural). You'll also need to set up the setting for hosting images on a web server. See the spectrum2 docs for more details

evgenyh commented 5 years ago

tried.PURPLE_MESSAGE_IMAGES . no change the suspected error in log is

28126: 2019-03-27 19:41:53,753 INFO  backend: conv_write_im()
28126: 2019-03-27 19:41:53,753 ERROR backend: GLib g_string_free: assertion 'string != NULL' failed

but this is more related to spectrum2 I assume.

hoehermann commented 5 years ago

@EionRobb Is there a different, more spectrum2-compatible way of handling images in libpurple? I used the first example I came across.

@evgenyh For a really dirty "solution", you can replace the body of the anonymous goroutine at purplegwa.go, line 297 with something like

err := qrcode.WriteFile(<-qr, qrcode.Medium, 256, "/tmp/whatsappqrcode.png")

. Instead of forwarding to the client, the server will store the image containing the QR code on its local filesystem. Assuming you have access and can open the image quickly enough, you should be able to login. I probably do not need to point out that this will lead to confusion if used with multiple connections at the same time.

evgenyh commented 5 years ago

@hoehermann thanks for reply, I'll try that. At least for confirming if it working. And btw, libpurple-hangouts have similar functionality of inline images and afaik, it works with spectrum. pls see this discussion spectrum2 closed issue

https://bitbucket.org/EionRobb/purple-hangouts/src/5e769791d282a6e5ae4d94dc66a1ff9d6904ec9c/hangouts_events.c?at=default&fileviewer=file-view-default#hangouts_events.c-531

EionRobb commented 5 years ago

@hoehermann the "most compatible" way is to use the libpurple request api. This has been used by other prpls for showing captcha images and getting the user to fill in the letters or whatever. Oh, maybe the notify api would be better since there's no human input required. Unfortunately, the way spectrum2 has been written, it has protocol-specific code to handle each of these request/notify api calls

Using the inline image system with the http image server, spectrum will save the qrcode to disk for its web server to provide, which is similar as what you're suggesting. Unfortunately again, getting the web server to work is finnicky, and I've only heard of one person who got it working.

hoehermann commented 5 years ago

Thank you both for your input. As far as I understood, the alternatives offer some, but no vast improvement over the current implementation. Consequently, I leave this as enhancement for later / maybe.

evgenyh commented 5 years ago

err := qrcode.WriteFile(<-qr, qrcode.Medium, 256, "/tmp/whatsappqrcode.png")

this works. a bit unusable though

hoehermann commented 5 years ago

a bit unusable though

I did not expect it to be any better.

I do not use spectrum2, so… Pull requests are welcome. ;)

evgenyh commented 5 years ago

golang is not my area of expertise, but will try to do my best :)

hoehermann commented 5 years ago

I never worked with go before, either. Takes a bit to get used to, but it seems solid.

This particular problem is probably tackled in the C part, though. It is just a hunch. The QR code is displayed with the same technique as a normal image message. Whatever solution is found – it should pave the road for both use-cases.

rogora commented 5 years ago

I've been testing this, and image inlining works well for me, once the "http image server" is set up correctly. Modifying libgowhatsapp.c:135 as suggested, I can see the QR code in my chat (tested with gajim), and complete the login successfully.

The real problem that needs a fix is another one though. Apparently, for every image message received, both Spectrum 2 and this plugin try to free the memory containing image data, and this results in a crash of the Spectrum 2 component, and a loss of the whatsapp web session as a consequence. I patched the Spectrum 2 libpurple backend to avoid freeing such memory when the protocol is prpl-hehoe-gowhatsapp, but I'm not sure this is the ideal thing to do.

Who should be responsible for freeing the memory containing the image data?

EionRobb commented 5 years ago

From https://developer.pidgin.im/doxygen/2.7.11/html/imgstore_8h.html#6e992b86c90965143d380c9454132749

data | Pointer to the image data, which the imgstore will take ownership of and free as appropriate. If you want a copy of the data, make it before calling this function.

hoehermann commented 5 years ago

My bad. Thanks for reporting @rogora and thank you for your help Eion.

XP-Fan commented 5 years ago

Hey, did anyone get this running with spectrum2 now and if so can he advice a friend of mine how to do it quickly? Actually I'm blind, so I can not really use the original whatsApp in an productive manner. However, since before 2 weeks I was using whapp-irc, which is now broken and I can not reach the maintainer. Thus, now, I'm pretty much fucked and desperately seeking a solution. A friend of mine is operating an XMPP-server, also for my domain, and he also has spectrum so if he gets adviced, he could implement this for me. Hoehermann do you have still interest in completing this? Actually I would at least also need the possibility to receive voice messages as audiofiles. I don't care whether as link or as XMPP Filetransfer. Even without that it would be a big help for the short run, and on the long run I could also pull out my paypal if everything finally works out.

hoehermann commented 5 years ago

Hi @XP-Fan. I wanted to add support for media messages anyway. Due to your request, I figured I could do so today. Hand-tailored for you, there now is a new branch. I also uploaded a binary for your convenience. Files are downloaded into the "purple home directory" – whatever that means for spectrum2. It works for me in Pidgin. The downloaded files are displayed as local file links. Some kind of translation probably needs to be done for use with spectrum2. Report back in case you need adjustments. Please note that this version was quickly thrown together and not well tested.

XP-Fan commented 5 years ago

Hi, at first, many thanks for wanting to help me! Unfortunately we do have one more severe problem now: The friend I mentioned is using an docker-image of spectrum, where libpurple is within. I did not know that and I personally do not have any experience with XMPP-servers and stuff, not even with linux. I do have Fedora running on an computestick, so maybe you're willing to help me make it work there over SSH? Or you could prepare everything within another docker container which he would just have to fire up and give ports to it? Dunno whether 2 instances of spectrum could connect to the same XMPP-Server, but if yes, that might also be a possibility? But if you do so, indeed, an HTTP-Server would be great for the files and the QR-Code…

hoehermann commented 5 years ago

Please note that I have no experience with spectrum2 whatsoever. I do not know if the path you are currently trying is the easiest – it sure sounds complicated to me. I do not know how your blindness affects your ability to use a computer, but you might want to check out Finch. It can be controlled by using only the keyboard, it natively supports purple-gowhatsapp and there even is a text-to-speech plug-in. Apart from that, I am not up for administering other people's systems. I am sorry.

XP-Fan commented 5 years ago

Well, I was talking with someone from the spectrum team, he sais it's rather easy to integrate your plugin into the docker-image, so I've just gotta wait till he finishes I suppose. As for Finch, I would be interested in that, but unfortunately it seems not to be available on Windows?

hoehermann commented 5 years ago

I do not like the prospect of publishing this plug-in in that manner, but I'll put up with that, I guess. Who did you speak to? In case of a co-operation, I'd rather not play Chinese Whispers.

Indeed, Finch is only available for Linux-like systems.

thundergreen commented 5 years ago
126: 2019-07-16 20:56:12,817 INFO  libpurple: account:Destroying account 0x55ab69c2c6b0
126: 2019-07-16 20:56:12,858 INFO  backend: Creating account with name '+33781852856' and protocol 'prpl-hehoe-gowhatsapp'
126: 2019-07-16 20:56:12,858 INFO  libpurple: account:Connecting to account +33781852856.
126: 2019-07-16 20:56:12,858 INFO  libpurple: connection:Connecting. gc = 0x55ab69c1a900
126: 2019-07-16 20:56:13,816 INFO  libpurple: gowhatsapp:Recieved: at 0 id  remote login@s.whatsapp.net sender  (fromMe 0)
126: 2019-07-16 20:56:13,816 INFO  backend: conv_write_im()
126: 2019-07-16 20:56:13,816 INFO  backend: conv_write_im(): ignoring a system message
126: 2019-07-16 20:56:13,817 INFO  libpurple: gowhatsapp:Recieved: at 0 id  remote login@s.whatsapp.net sender  (fromMe 0)
126: 2019-07-16 20:56:13,817 INFO  backend: conv_write_im()
126: 2019-07-16 20:56:13,817 INFO  backend: conv_write_im(): ignoring a system message
126: 2019-07-16 20:56:17,815 INFO  libpurple: util:Writing file accounts.xml to directory /var/lib/spectrum2/whatsapp.emevth.no-ip.biz
126: 2019-07-16 20:56:17,816 INFO  libpurple: util:Writing file /var/lib/spectrum2/whatsapp.emevth.no-ip.biz/accounts.xml
126: 2019-07-16 20:56:33,816 INFO  libpurple: gowhatsapp:Recieved: at 0 id (null) remote (null) sender (null) (fromMe 0)
126: 2019-07-16 20:56:33,816 INFO  libpurple: connection:Connection error on 0x55ab69c1a900 (reason: 0 description: error during login: qr code scan timed out
)
126: 2019-07-16 20:56:33,816 INFO  libpurple: account:Disconnecting account +33xxxxxxxxx (0x55ab69c1ab30)
126: 2019-07-16 20:56:33,816 INFO  libpurple: connection:Disconnecting connection 0x55ab69c1a900
126: 2019-07-16 20:56:33,816 INFO  libpurple: connection:Destroying connection 0x55ab69c1a900
126: 2019-07-16 20:56:33,835 ERROR backend: g_log purple_account_disconnect: assertion '!purple_account_is_disconnected(account)' failed
126: 2019-07-16 20:56:33,835 INFO  libpurple: account:Destroying account 0x55ab69c1ab30
126: 2019-07-16 20:56:37,624 INFO  backend: Exiting.
hoehermann commented 5 years ago

@thundergreen There is an option for spectrum compatibility. Please set "system-messages-are-ordinary-messages" to true. I want to add that to the readme.

The plug-in will then generate an image containing the QR for log-in and saves it into a file. With spectrum, the file location is /var/lib/spectrum2/whatsapp.emevth.no-ip.biz/whatsapp/login, I guess. In the front-end, a link is displayed. Right now, it is a local file link file:///var/lib/spectrum2/whatsapp.emevth.no-ip.biz/whatsapp/login. As far as I understand, spectrum comes with a HTTP server for exactly that scenario. I have no idea how to adjust the URL, though. It could be as easy as http://whatsapp.emevth.no-ip.biz/whatsapp/login, but I am totally guessing right now. I would gladly take your advice.

thundergreen commented 5 years ago

@hoehermann sorry for dumb question but where ? in the whatsapp.cfg?

hoehermann commented 5 years ago

I do not know where spectrum stores the plug-in's settings, either. I do not use spectrum myself. I am willing to improve this plug-in for spectrum, but I am unwilling to do end-user support for spectrum installations.

XP-Fan commented 5 years ago

Well, at first, sorry for my super late response, I had many exams… Actually, I was just asking within the spectrum-XMPP chat. A guy named "VT" said he could include the plugin. From the way he speaks about the spectrum stuff, and given that he is the owner of the chat room, I strongly suspect him to be the spectrum maintainer. However, as of now, he says he doesn't have time. Furthermore, he says that the plugin does do some stuff wrongly, such as file transfers. Since you said you would be willing to improve spectrum compatibility, you might want to talk to him: Just join spectrum%conference.spectrum.im, you might also find me in there, I'm Peter. As to me personally, I found sms-irc, (another WhatsApp Web IRC-Gateway), which works pretty good, the maintainer was as nice as to set it up for me, but as you might know, IRC has no typing-notifications, no unified file transfer, absolutely no MPoP-support and presence tracking is well… Unreliable. Furthermore Miranda does just allow up to 400 characters within an IRC-Message, so, on the long run, it would be awesome to see an WhatsApp Web XMPP-transport on an spectrum basis…

hoehermann commented 2 years ago

I am doing some preliminary work here on the switch to multi-device mode. https://github.com/tulir/whatsmeow is used as the back-end.

Current state:

Next up:

Disregarded for now:

Is this good for spectrum2?

vitalyster commented 2 years ago

What is purple's username? If that is case-sensitive then it is not possible to map case-sensitive username to case-insensitive localpart of the XMPP address (https://datatracker.ietf.org/doc/html/rfc7622#section-3.3). +xxxxxxxxxx numeric accounts will work great.

Image issues are subject to change in spectrum2 itself and not a problem at all.

hoehermann commented 2 years ago

Sounds good. On the purple side, the user is free to chose the account's username. It is indeed case-sensitive, but for numbers it does not matter. I recommend the WhatsApp notation <phone number>@s.whatsapp.net, but even that is always all lowercase.

vitalyster commented 2 years ago

This username mostly unused in spectrum, I mean usernames of user buddies, they should be numeric and not "user-friendly" screen names like some plugins do

hoehermann commented 2 years ago

Thank you for the input. I take care in never changing contacts JIDs as it would probably mess something up. I considered many factors from this and other issues during the re-write. You can see some preliminary results being discussed here: https://github.com/hoehermann/purple-gowhatsapp/issues/90#issuecomment-1007968949

hoehermann commented 2 years ago

@vitalyster May I set the username during the pairing process or is the username considered read-only in spectrum? @yourealwaysbe Do you know if that would work for bitlbee?

Update: Never mind. It was a brain-fart. It is way more sensible to munge all relevant information in the password string – just as @yourealwaysbe did in the go-whatsapp version.

vitalyster commented 2 years ago

I think username is not used in spectrum at all

hoehermann commented 2 years ago

@evgenyh @rogora @XP-Fan @thundergreen The re-written version https://github.com/hoehermann/purple-gowhatsapp/tree/whatsmeow is much more mature now. I would appreciate more spectrum-related tests and appreciate your feedback.

vitalyster commented 2 years ago

Should spectrum-compatibility option work with whatsmeow branch? I can not receive qr code

hoehermann commented 2 years ago

Currently, the spectrum compatibility option is only used for "soft" error messages regarding a specific conversation, e.g. "the message could not be sent". In Pidgin, these are shown as system messages. I have been told system messages are not shown in spectrum at all, so I create a fake non-system message for spectrum.

The QR code is shown via the purple request API. Alternatively, you can set qrcode-size to 0 to render the QR-code to text. This was a much-requested feature #35 so I hope it helps. :)

If you are going to connect to more than one WhatsApp account (what would be a sensible use-case for spectrum, I assume), you may need to use mysql or postgres as a backend for whatsmeow (see the readme) due to a limitation of the SQlite driver, as hinted here. I have no information whether this actually is a problem.

vitalyster commented 2 years ago

@hoehermann please check https://pastebin.com/eMwDL9zS - I did not see any purple requests in logs, it works before on master branch

vitalyster commented 2 years ago

the spectrum compatibility option is only used

I did not receive such option on PurplePluginProtocolInfo::protocol_options structure: https://github.com/SpectrumIM/spectrum2/blob/master/backends/libpurple/main.cpp#L324

hoehermann commented 2 years ago

I did not receive such option

That is a bug. I forgot to add that to the list of options. Please stand by.

Update: Fixed in 0804c4a.

I did not see any purple requests in logs, it works before on master branch

That is weird. I actually copied that part of the code from the master branch. recieved login (level 0) for account … is a good sign, but then purple_request_fields is not handled. I am now building spectrum from source to test this for myself.

Edit: Nope, after one hour of chasing down dependencies, I am drawing a line. https://swift.im/packages/ubuntu/focal does not exist. I only have Ubuntu Focal, Debian Bullseye, Arch and Windows 10 at hand right now. I could probably set up another virtual machine, but I am unwilling to do so right now.

Side note: The instructions on https://spectrum.im/documentation/installation/packages_debian_ubuntu.html have errors in them: There is a pipe missing in line 1 and build-dep needs sudo.

vitalyster commented 2 years ago

All build dependencies for bullseye including libswiften are in spectrum repo, deb https://packages.spectrum.im/spectrum2/ bullseye main, no need to use swift.im repo, it is outdated

vitalyster commented 2 years ago

Well, I tested everything and found the problem - UI for purple_request_fields was never implemented in Spectrum. (Only for purple_request_input which is not our case) The correct way to display an image is to send a message with PURPLE_MESSAGE_IMAGES flag and image data

EionRobb commented 2 years ago

I'm trying to do a similar thing in the discord prpl, but looking at whether the ui supports the request_fields https://github.com/EionRobb/purple-discord/blob/qrcode-auth/discord_rsa.c#L46-L48 - Haven't managed to get it going for bitlbee yet, but might work for spectrum?

vitalyster commented 2 years ago

@EionRobb spectrum will lookup for image id only when PURPLE_MESSAGE_IMAGES flag is set - https://github.com/SpectrumIM/spectrum2/blob/master/backends/libpurple/main.cpp#L1510

hoehermann commented 2 years ago

@vitalyster Thank you for looking into it. I was told images are kind of hard to do in spectrum. That is why I currently do not do images at all (I treat them as downloads). I was under the impression using purple_request_fields would be the way to go. I am sorry for the misunderstanding. However, I added a much requested text rendering mode. Does setting qrcode-size to 0 produce messages?

vitalyster commented 2 years ago

qr-code integer option does not work in Spectrum because of bug with integer options :) So we are unable to test text-based qr-code and waiting for PURPLE_MESSAGE_IMAGES :)

hoehermann commented 2 years ago

I did not know of that bug. I am sorry for the inconvenience. I quickly changed the option to be a boolean in the dev branch. I cannot test at the moment since my phone's camera died and I do not have a second device at hand.

I currently do not plan to implement embedded images again. People urged me to use the xfer API and so I did.

vitalyster commented 2 years ago

What is the problem with embedded images? Isn't xfer api is something which will not display image but show file in downloads list?

hoehermann commented 2 years ago

Yes xfer API will show the file in the downloads. At least that is what happens in Pidgin. Works reliably.

I have received reports of embedded images requiring additional configuration in spectrum and/or bitlbee (cannot tell from the top of my head which one it was) so people were not using it.
In Pidgin, if you embed an image, it is not stored on disk. That made some other people unhappy.
I came to realize that I cannot make everyone happy – no matter which way I choose. I could of course add configuration options for every possible use-case, but most of those would be untested and therefore probably released with bugs, resulting in even more complains.

The plug-in reached "works for me" the state two weeks ago. Ever since then, most of my work I did for other people, implementing functionality I do not use myself. I was willing to get this working with spectrum, but compared to Pidgin, testing against spectrum feels rather frustrating to me.