Skip to content

Instantly share code, notes, and snippets.

@mervick
Forked from erickdsama/rwas.py
Created December 7, 2020 00:03
Show Gist options
  • Save mervick/6d545dc3946b2155c26e3d0ea5333ed7 to your computer and use it in GitHub Desktop.
Save mervick/6d545dc3946b2155c26e3d0ea5333ed7 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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment