Skip to content
This repository has been archived by the owner on Nov 2, 2023. It is now read-only.

Add keep-alive support for a more persistent connection #21

Merged
merged 27 commits into from
Jan 30, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
55513de
Merge pull request #5 from p4kl0nc4t/develop
lc-at Jun 9, 2020
64af9b6
Update README.md
lc-at Jun 9, 2020
986b6b9
Update README.md
lc-at Jan 17, 2021
6168350
Bump pyyaml from 5.3.1 to 5.4 in /kyros
dependabot[bot] Mar 25, 2021
228b6b5
Bump websockets from 8.1 to 9.1
dependabot[bot] Jun 11, 2021
06dab2d
Bump websockets from 8.1 to 9.1 in /kyros
dependabot[bot] Jun 11, 2021
b6a0409
Merge pull request #13 from p4kl0nc4t/dependabot/pip/kyros/websockets…
lc-at Aug 31, 2021
414be72
Merge pull request #12 from p4kl0nc4t/dependabot/pip/websockets-9.1
lc-at Aug 31, 2021
f30d677
Merge pull request #11 from p4kl0nc4t/dependabot/pip/kyros/pyyaml-5.4
lc-at Aug 31, 2021
8823fcd
Bump pyyaml from 5.3.1 to 5.4
dependabot[bot] Aug 31, 2021
1f03774
Merge pull request #10 from p4kl0nc4t/dependabot/pip/pyyaml-5.4
lc-at Aug 31, 2021
b713ed2
Update .gitattributes
lc-at Aug 31, 2021
2d36ee9
Update .gitattributes
lc-at Aug 31, 2021
63ada35
Update .gitattributes
lc-at Sep 8, 2021
4274548
Add support for WhatsApp keep alive
Jan 15, 2022
58ac7ef
Call keep alive after command Conn
Jan 15, 2022
d914eee
Add support for websocket keep alive
Jan 15, 2022
90e129d
Fix invalid comma
Jan 15, 2022
afde8cd
Fix styles
Jan 15, 2022
156e8fe
Update documentation to docstrings
Jan 15, 2022
bc986ae
Add WhatsApp protocol binary reader
Jan 29, 2022
2362a80
Allow websocket to differentiate from plaintext/binary message
Jan 29, 2022
278bca2
Fix websocket hangs and close after time
Jan 29, 2022
74358c0
Fix proto import
Jan 30, 2022
bdeb6fd
Add message data handler
Jan 30, 2022
783d4ab
Update readme documentation
Jan 30, 2022
e69f5f9
Initial support for binary message reader
Jan 30, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
html/* linguist-vendored
html/kyros linguist-vendored
html/kyros/* linguist-vendored
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ Kyros, for now, is a Python interface to communicate easier with WhatsApp Web AP
It provides an interface to connect and communicate with WhatsApp Web's websocket server.
Kyros will handle encryption and decryption kind of things.
In the future, Kyros is aimed to provide a full implementation of WhatsApp Web API which will give developers
a clean interface to work with (more or less like ![go-whatsapp](https://github.com/Rhymen/go-whatsapp)).
a clean interface to work with (more or less like [go-whatsapp](https://github.com/Rhymen/go-whatsapp)).
This module is designed to work with Python 3.6 or latest.
Special thanks to the creator of ![whatsapp-web-reveng](https://github.com/sigalor/whatsapp-web-reveng)
and ![go-whatsapp](https://github.com/Rhymen/go-whatsapp). This project is largely motivated by their work.
Special thanks to the creator of [whatsapp-web-reveng](https://github.com/sigalor/whatsapp-web-reveng)
and [go-whatsapp](https://github.com/Rhymen/go-whatsapp). This project is largely motivated by their work.
Please note that Kyros is not meant to be used actively in production servers as it is currently not
production ready. Use it at your own risk.

Expand All @@ -25,7 +25,7 @@ import logging

import pyqrcode

from kyros import Client, WebsocketMessage
import kyros

logging.basicConfig()
# set a logging level: just to know if something (bad?) happens
Expand Down Expand Up @@ -61,7 +61,7 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
```
A "much more detailed documentation" kind of thing for this project is available ![here](https://p4kl0nc4t.github.io/kyros/).
A "much more detailed documentation" kind of thing for this project is available [here](https://p4kl0nc4t.github.io/kyros/).
You will see a piece of nightmare, happy exploring! Better documentation are being planned.

## Contribution
Expand Down
4 changes: 2 additions & 2 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pylint-django==2.0.12
pylint-flask==0.6
pylint-plugin-utils==0.6
PyQRCode==1.2.1
PyYAML==5.3.1
PyYAML==5.4
regex==2020.4.4
requirements-detector==0.6
rope==0.16.0
Expand All @@ -34,6 +34,6 @@ snowballstemmer==2.0.0
toml==0.10.0
typed-ast==1.4.1
websocket-client==0.57.0
websockets==8.1
websockets==9.1
wrapt==1.11.2
yapf==0.30.0
6 changes: 6 additions & 0 deletions kyros/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ async def wait_qr_scan():
self.session.enc_key = self.session.keys_decrypted[:32]
self.session.mac_key = self.session.keys_decrypted[32:64]

# First call of keep alive after session initialized
await self.websocket.keepAlive()

qr_fragments = [
self.session.server_id,
base64.b64encode(self.session.public_key.public).decode(),
Expand Down Expand Up @@ -184,6 +187,9 @@ async def restore():
self.session.server_token = info["serverToken"]

self.websocket.load_session(self.session) # reload references

# First call of keep alive after session reloaded
await self.websocket.keepAlive()
return self.session

try:
Expand Down
4 changes: 2 additions & 2 deletions kyros/dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pylint-django==2.0.12
pylint-flask==0.6
pylint-plugin-utils==0.6
PyQRCode==1.2.1
PyYAML==5.3.1
PyYAML==5.4
regex==2020.4.4
requirements-detector==0.6
rope==0.16.0
Expand All @@ -56,7 +56,7 @@ typed-ast==1.4.1
typing==3.7.4.1
watchdog==0.10.2
websocket-client==0.57.0
websockets==8.1
websockets==9.1
wrapt==1.11.2
yapf==0.30.0
zipp==3.1.0
25 changes: 24 additions & 1 deletion kyros/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@

logger = logging.getLogger(__name__) # pylint: disable=invalid-name

class Timer:
def __init__(self, timeout, callback):
self._timeout = timeout
self._callback = callback
self._task = asyncio.ensure_future(self._job())

async def _job(self):
await asyncio.sleep(self._timeout)
await self._callback()

def cancel(self):
self._task.cancel()

class WebsocketMessage:
"""
Expand Down Expand Up @@ -142,10 +154,16 @@ async def connect(self) -> None:
listener."""
logger.debug("Connecting to ws server")
self.websocket = await websockets.connect(
constants.WEBSOCKET_URI, origin=constants.WEBSOCKET_ORIGIN)
constants.WEBSOCKET_URI, origin=constants.WEBSOCKET_ORIGIN, close_timeout = None,ping_interval = None)
reinier-millo marked this conversation as resolved.
Show resolved Hide resolved
logger.debug("Websocket connected")
self._start_receiver()

async def keepAlive(self):
reinier-millo marked this conversation as resolved.
Show resolved Hide resolved
if self.websocket and self.websocket.open:
await self.websocket.send('?,,')
# Send keepalive every 10 seconds
Timer(10.0, self.keepAlive)

def load_session(self, session: Session) -> None:
"""Loads a session. This will make sure that all references are
updated. If there is a key change, the new key will be used to
Expand Down Expand Up @@ -177,6 +195,11 @@ async def receiver():
continue

raw_message = self.websocket.messages.pop()

# Ignore server timestamp responses
if raw_message[:1] == "!":
continue

try:
message = WebsocketMessage.unserialize(
raw_message, self.get_keys())
Expand Down