Skip to content

Instantly share code, notes, and snippets.

@erickdsama
Last active March 4, 2024 19:21
Show Gist options
  • Save erickdsama/8b312635ca34770f69d08f58d65f69d1 to your computer and use it in GitHub Desktop.
Save erickdsama/8b312635ca34770f69d08f58d65f69d1 to your computer and use it in GitHub Desktop.
Class to read and write messages to Whatsapp through of the ADB. You need a android Device with Sqlite3 installed and ADB service.
# coding=utf-8
import json
import time
from subprocess import check_output, CalledProcessError
class WHO:
FROM_ME = "key_from_me == 1"
OTHERS = "key_from_me != 1"
ALL = ""
class TYPE:
GPS = 1
IMAGE = 2
TEXT = 3
class COLUMN:
_id = id = 0
key_remote_jid = 1
key_from_me = 2
key_id = 3
status = 4
needs_push = 5
data = message = 6
timestamp = 7
media_url = 8
media_mime_type = 9
media_wa_type = 10
media_size = 11
media_name = 12
media_caption = 13
media_hash = 14
media_duration = 15
origin = 16
latitude = 17
longitude = 18
thumb_image = 19
remote_resource = 20
received_timestamp = 21
send_timestamp = 22
receipt_server_timestamp = 23
receipt_device_timestamp = 24
read_device_timestamp = 25
played_device_timestamp = 26
raw_data = 27
recipient_count = 28
participant_hash = 29
starred = 30
quoted_row_id = 31
mentioned_jids = 32
multicast_id = 33
edit_version = 34
media_enc_hash = 35
payment_transaction_id = 36
class RWAS:
"""Rest WhatsApp Application Service
Class to read and write messgaes directly to an android device [Sqlite3 is needed]
Args:
emulator (str): ID from your Android device, can be an Android phone or a Emulator with Sqlite3 installed.
Note:
if you only use one Device is not necesary pass the 'emulator' arg, It will be detected automatically
"""
def __init__(self, emulator=None):
self.emulator = emulator
def rwas_check_output(self, last_id=None, who=None):
if last_id is None:
query_str = " WHERE {}".format(who) if (who != WHO.ALL) else ""
else:
query_str = " AND {}".format(who) if (who != WHO.ALL) else ""
query_str = "WHERE _id>{} {}".format(last_id, query_str)
if self.emulator is None:
return check_output(
"adb shell 'sqlite3 /data/data/com.whatsapp/databases/msgstore.db \"select * from messages {};\"'".format(query_str), shell=True)
else:
return check_output(
"adb -s {} shell 'sqlite3 /data/data/com.whatsapp/databases/msgstore.db \"select * from messages {};\"'".format(self.emulator, query_str), shell=True)
def read(self, last_id=None, who=WHO.OTHERS):
""" Method to read the messages from the database of whatsapp
Args:
last_id (int): The last _id that do u want
who (WHO): Whos the message emitter
Note:
if you don't pass tha last_id param, returns all messages
Returns:
DATA if successful, None otherwise.
"""
try:
return self.DATA(self.rwas_check_output(last_id=last_id, who=who))
except CalledProcessError as e:
return None
def send(self, message=None, location=None, remote_jid=None):
build_message = self.BuildMessage(message=message, location=None, remote_jid=remote_jid)
print build_message.chat_string
try:
print check_output("adb shell pkill com.whatsapp", shell=True)
print check_output("adb shell chmod 777 /data/data/com.whatsapp/databases/msgstore.db", shell=True)
print check_output(build_message.chat_string, shell=True)
print check_output(build_message.list_string, shell=True)
print check_output(build_message.update_string, shell=True)
print check_output("adb shell am start -n com.whatsapp/.Main", shell=True)
except CalledProcessError as e:
print e
class DATA:
def __init__(self, dumped=None):
self.dumped = dumped
def parse_to_array(self):
fields = []
rows = self.dumped.split("|\r\n")
del rows[-1]
for row in rows:
elements = row.split("|")
fields.append(elements)
return fields
def parse_to_dict(self):
array = self.parse_to_array()
messages = []
for row in array:
data = {
"_id": row[COLUMN.id],
"message": row[COLUMN.message],
"latitude": row[COLUMN.latitude],
"longitude": row[COLUMN.longitude],
"med_du": row[COLUMN.media_duration],
"key_remote_jid": row[COLUMN.key_remote_jid],
}
messages.append(data)
data = {
"messages": messages
}
return data
def parse_to_json(self):
""" Convert the data to JSON object
Returns:
A Json object of the data fetched
"""
return json.dumps(self.parse_to_dict(), ensure_ascii=False)
class BuildMessage:
def __init__(self, message=None, location=None, remote_jid=None):
self.location = location
self.message = message
self.remote_jid = remote_jid
@property
def chat_string(self):
"""str: Chat string query to insert """
l1 = int(round(time.time() * 1000))
l2 = int(l1 / 1000)
k = "-1150867590"
return """adb shell "sqlite3 /data/data/com.whatsapp/databases/msgstore.db \\"INSERT INTO messages (key_remote_jid, key_from_me, key_id, status, needs_push, data, timestamp, MEDIA_URL, media_mime_type, media_wa_type, MEDIA_SIZE, media_name , latitude, longitude, thumb_image, remote_resource, received_timestamp, send_timestamp, receipt_server_timestamp, receipt_device_timestamp, raw_data, media_hash, recipient_count, media_duration, origin) VALUES ('{}', 1,'{}-{}', 0,0, '{}',{},'','', 0, 0,'', 0.0,0.0,'','',{}, -1, -1, -1,0 ,'',0,0,0);\\""
""".format(self.remote_jid, l2, k, self.message, l1, l1)
@property
def list_string(self):
"""str: List chat query to insert """
return """ adb shell "sqlite3 /data/data/com.whatsapp/databases/msgstore.db \\"insert into chat_list (key_remote_jid) select '{0}' where not exists (select 1 from chat_list where key_remote_jid='{0}');\\"" """.format(
self.remote_jid)
@property
def update_string(self):
"""str: List chat query to update based on list insert """
return """ adb shell "sqlite3 /data/data/com.whatsapp/databases/msgstore.db \\"update chat_list set message_table_id = (select max(messages._id) from messages) where chat_list.key_remote_jid='{}';\\"" """.format(
self.remote_jid)
@erickdsama
Copy link
Author

erickdsama commented Feb 28, 2018

if you want to use the Class you only need call it of this way.

rwas_service = RWAS(emulator=None) # class call
rwas_service.read(last_id=None).parse_to_json() # to read all on and parse to json
rwas_service.send(message="Hello world from mexico", remote_jid="526561234567@s.whatsapp.net") # to send change the remote_jid

@joaoguariglia
Copy link

Hello I'm new to programming, I'm emulating anbox with whatsapp on ubuntu and I would like to run your application, but I have no idea how to do it, I access the normal adb shell, and this is the only device on my machine that emulates android, and now what do i need to do? I tried to run it on my host machine:

python -c rwas.py

But nothing happens

@erickdsama
Copy link
Author

erickdsama commented Feb 15, 2020 via email

@erickdsama
Copy link
Author

erickdsama commented Feb 15, 2020 via email

@Manjit2003
Copy link

Sorry but it is saying

/system/bin/sh: sqlite3: not found

Help me...

@Manjit2003
Copy link

Does it require the device to be rooted??

@bslava
Copy link

bslava commented Apr 27, 2020

I have the same issue. Please help.

@fokker1984
Copy link

Wonderful, this is more than I expected.
Is there any way to send an image using this method?

@erickdsama
Copy link
Author

Does it require the device to be rooted??

you can use Genymotion. and install GAPPS, if you want to use a phisical device you need to rooted and install busybox

Sorry but it is saying

/system/bin/sh: sqlite3: not found

Help me...

busybox can help you with that

@erickdsama
Copy link
Author

erickdsama commented May 4, 2020

I have the same issue. Please help.

hi you can install busybox

https://forum.xda-developers.com/showthread.php?t=2195692

@joaoguariglia
Copy link

Erick logró que funcionara, ahora el problema es, ¿cómo veo los mensajes? Seguí tu ejemplo de Python, pero como no sé mucho sobre Python, ¿puedes hacer algunos ejemplos de leer el mensaje por usuario o por mensajes nuevos?

@salikhov829
Copy link

salikhov829 commented Sep 9, 2020

Hi, cool class, but it works for me only if i try to send the message to user, who sent any message to me before.
If a chat list on device is empty, script only inserts in database, then it starts app, but do not send the message))
Do you have any idea how to fix it?)

@kimseler14
Copy link

Can you tell us how to use it?

@erickdsama
Copy link
Author

Hi, cool class, but it works for me only if i try to send the message to user, who sent any message to me before.
If a chat list on device is empty, script only inserts in database, then it starts app, but do not send the message))
Do you have any idea how to fix it?)

Hi, thanks. before nothing, sorry for my bad english. That's maybe a error in the insert of list

        def list_string(self):
            """str: List chat query to insert """
            return """ adb shell "sqlite3 /data/data/com.whatsapp/databases/msgstore.db \\"insert into chat_list (key_remote_jid) select '{0}' where not exists (select 1 from chat_list where key_remote_jid='{0}');\\"" """.format(
                    self.remote_jid)

let me fix this weekend and update the class

how ever i have an library in pip, you can install and use it.

RWAS

@erickdsama
Copy link
Author

Can you tell us how to use it?

Hi, first you need genymotion with Whatsapp installed, once you have installed it. use the file like ihe example in above

rwas_service = RWAS(emulator=None) # class call rwas_service.read(last_id=None).parse_to_json() # to read all on and parse to json rwas_service.send(message="Hello world from mexico", remote_jid="526561234567@s.whatsapp.net") # to send change the remote_jid

@kimseler14
Copy link

kimseler14 commented Sep 12, 2020

Can you tell us how to use it?

Hi, first you need genymotion with Whatsapp installed, once you have installed it. use the file like ihe example in above

rwas_service = RWAS(emulator=None) # class call rwas_service.read(last_id=None).parse_to_json() # to read all on and parse to json rwas_service.send(message="Hello world from mexico", remote_jid="526561234567@s.whatsapp.net") # to send change the remote_jid

thank you very much for answering me. i wonder how can manually send command from adb? can u help me

example, i got error always:

└──╼ $adb shell 'sqlite3 /data/data/com.whatsapp/databases/msgstore.db "select * from messages;"'
sqlite3: Error: too many options: "acct"
Use -help for a list of options.
/system/bin/sh: ": not found

edit: i solve like this
import os
os.system('adb shell "su -c 'sqlite3 /data/data/com.whatsapp/databases/msgstore.db \"select * from messages\"'"')

but i can't modify insert string, i can't handle exception("\") in string. can u help me for insert method

l1 = int(round(time.time() * 1000))
l2 = int(l1 / 1000)
k = "-1150867590"
jid = "90000@s.whatsapp.net"
message = "test"

os.system('adb shell "su -c 'sqlite3 /data/data/com.whatsapp/databases/msgstore.db \"INSERT INTO messages (key_remot........... "'"')

edit2:
i test insert witout timestamp but i got error :
Error: near "@s": syntax error

└──╼ $adb shell "su -c 'sqlite3 /data/data/com.whatsapp/databases/msgstore.db "INSERT INTO messages (key_remote_jid, key_from_me, key_id, status, needs_push, data, timestamp, MEDIA_URL, media_mime_type, media_wa_type, MEDIA_SIZE, media_name , latitude, longitude, thumb_image, remote_resource, received_timestamp, send_timestamp, receipt_server_timestamp, receipt_device_timestamp, raw_data, media_hash, recipient_count, media_duration, origin) VALUES ('5216562724890@s.whatsapp.net', 1,'1599942971--1150867590', 0,0, 'Hello world from mexico',1599942971860,'','', 0, 0,'', 0.0,0.0,'','',1599942971860, -1, -1, -1,0 ,'',0,0,0)"'"
Error: near "@s": syntax error

@salikhov829
Copy link

salikhov829 commented Sep 14, 2020

after insert in chat_list it is not visible, i think it is a problem, do you have a good query for inserting?)
if i run script several times, then writing message via wa.me, it sends all messages from script, which i send before from script)

@salikhov829
Copy link

now it can send messages, but very slowly, 40-60 seconds per 1 msg)
erickdsama, can you send to me your contacts or telegram please?)
if you have a time to conversations, sometimes
my mail is salikhov829@gmail.com

@JayeshThatte
Copy link

for sending messages you can use api.whatsapp.com
f'am start -a android.intent.action.VIEW -d "https://api.whatsapp.com/send?phone={number}&text={text}"'

@surajsonee
Copy link

I have modified this script, currently its working fine with python3.
contact me on skype: suraj.prasad1990

@rsharmaktl
Copy link

should I modify WhatsApp message using this script. if you any idea then please help me +919034132449

@Dinibewerbig
Copy link

Hi Erick

Thank you for your script. Awesome!

Saidly I get the following error when I run rwas.py with the following lines inside rwas.py.
rwas_service = RWAS(emulator=None) # class call
rwas_service.read(last_id=None).parse_to_json() # to read all on and parse to json
rwas_service.send(message="Hello world from mexico", remote_jid="5265612345@s.whatsapp.net") # to send change the remote_jid

Any idea why it doesnt work?

ERROR

thomas$ python3 rwas.py
Traceback (most recent call last):
File "/Users/thomas/rwas.py", line 190, in
rwas_service.read(last_id=None).parse_to_json() # to read all on and parse to json
File "/Users/thomas/rwas.py", line 157, in parse_to_json
return json.dumps(self.parse_to_dict(), ensure_ascii=False)
File "/Users/thomas/rwas.py", line 135, in parse_to_dict
array = self.parse_to_array()
File "/Users/thomas/rwas.py", line 127, in parse_to_array
rows = self.dumped.split("|\r\n")
TypeError: a bytes-like object is required, not 'str'

@Dinibewerbig
Copy link

Hi Erick

Could it be that your script doesnt work anymore with the a new version of whatsapp? Which version have you used, when your script still worked. Do you remember?

Brigado!

@Dinibewerbig
Copy link

This happens when I call the send.message function.

b''
b''
b'Error: no such table: messages\r\n'
b'Error: no such table: chat_list\r\n'
b'Error: no such table: chat_list\r\n'
b'Starting: Intent { cmp=com.whatsapp/.Main }\r\n'

seems like the database of whatsapp has changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment