mirror of
https://github.com/JJTech0130/pypush.git
synced 2025-01-22 11:18:29 +00:00
preparing some stuff
This commit is contained in:
parent
da483b995b
commit
3904bf9e3f
23
demo.py
23
demo.py
@ -168,6 +168,7 @@ def fixup_handle(handle):
|
||||
|
||||
|
||||
current_participants = []
|
||||
sms = False
|
||||
current_effect = None
|
||||
while True:
|
||||
im.activate_sms() # We must call this always since SMS could be turned off and on again, and it might have been on before this.
|
||||
@ -228,6 +229,13 @@ while True:
|
||||
if len(msg) < 2 or msg[1] == "":
|
||||
print("filter [recipients]")
|
||||
else:
|
||||
if msg[1] == "sms":
|
||||
print("Filtering to SMS")
|
||||
msg = msg[1:]
|
||||
sms = True
|
||||
else:
|
||||
sms = False
|
||||
|
||||
print(f"Filtering to {[fixup_handle(h) for h in msg[1:]]}")
|
||||
current_participants = [fixup_handle(h) for h in msg[1:]]
|
||||
im._cache_keys(
|
||||
@ -256,15 +264,16 @@ while True:
|
||||
if msg.startswith("\\"):
|
||||
msg = msg[1:]
|
||||
|
||||
imsg = imessage.iMessage.create(
|
||||
im,
|
||||
msg,
|
||||
current_participants,
|
||||
if sms:
|
||||
import uuid
|
||||
m = imessage.SMSReflectedMessage(
|
||||
msg, user.current_handle, current_participants, uuid.uuid4()
|
||||
)
|
||||
else:
|
||||
m = imessage.iMessage.create(im, msg, current_participants)
|
||||
m.effect = current_effect
|
||||
|
||||
imsg.effect = current_effect
|
||||
|
||||
im.send(imsg)
|
||||
im.send(m)
|
||||
current_effect = None
|
||||
else:
|
||||
print("No chat selected, use help for help")
|
||||
|
122
imessage.py
122
imessage.py
@ -147,7 +147,7 @@ class Message:
|
||||
@dataclass
|
||||
class SMSReflectedMessage(Message):
|
||||
def from_raw(message: bytes, sender: str | None = None) -> "SMSReflectedMessage":
|
||||
"""Create a `SMSIncomingMessage` from raw message bytes"""
|
||||
"""Create a `SMSReflectedMessage` from raw message bytes"""
|
||||
|
||||
# Decompress the message
|
||||
try:
|
||||
@ -158,7 +158,7 @@ class SMSReflectedMessage(Message):
|
||||
|
||||
message = plistlib.loads(message)
|
||||
|
||||
logger.debug(f"Decoding SMSReflectedMessage: {message}")
|
||||
logger.info(f"Decoding SMSReflectedMessage: {message}")
|
||||
|
||||
return SMSReflectedMessage(
|
||||
text=message["mD"]["plain-body"],
|
||||
@ -169,6 +169,41 @@ class SMSReflectedMessage(Message):
|
||||
_compressed=compressed,
|
||||
)
|
||||
|
||||
def to_raw(self) -> bytes:
|
||||
# {'re': [{'id': '+14155086773', 'uID': '4155086773', 'n': 'us'}], 'ic': 0, 'mD': {'handle': '+14155086773', 'guid': imessage.py:201
|
||||
# '35694E24-E265-4D5C-8CA7-9499E35D0402', 'replyToGUID': '4F9BC76B-B09C-2A60-B312-9029D529706B', 'plain-body': 'Test sms', 'service':
|
||||
# 'SMS', 'sV': '1'}, 'fR': True, 'chat-style': 'im'}
|
||||
#pass
|
||||
# Strip tel: from participants, making sure they are all phone numbers
|
||||
#participants = [p.replace("tel:", "") for p in self.participants]
|
||||
|
||||
d = {
|
||||
"re": [{"id": p} for p in self.participants],
|
||||
"ic": 0,
|
||||
"mD": {
|
||||
"handle": self.participants[0] if len(self.participants) == 1 else None,
|
||||
#"handle": self.sender,
|
||||
"guid": str(self.id).upper(),
|
||||
#"replyToGUID": "3B4B465F-F419-40FD-A8EF-94A110518E9F",
|
||||
#"replyToGUID": str(self.id).upper(),
|
||||
"xhtml": f"<html><body>{self.text}</body></html>",
|
||||
"plain-body": self.text,
|
||||
"service": "SMS",
|
||||
"sV": "1",
|
||||
},
|
||||
#"fR": True,
|
||||
"chat-style": "im" if len(self.participants) == 1 else "chat"
|
||||
}
|
||||
|
||||
# Dump as plist
|
||||
d = plistlib.dumps(d, fmt=plistlib.FMT_BINARY)
|
||||
|
||||
# Compress
|
||||
if self._compressed:
|
||||
d = gzip.compress(d, mtime=0)
|
||||
|
||||
return d
|
||||
|
||||
def __str__(self):
|
||||
return f"[SMS {self.sender}] '{self.text}'"
|
||||
|
||||
@ -279,6 +314,22 @@ class iMessage(Message):
|
||||
def __str__(self):
|
||||
return f"[iMessage {self.sender}] '{self.text}'"
|
||||
|
||||
MESSAGE_TYPES = {
|
||||
100: ("com.apple.madrid", iMessage),
|
||||
140: ("com.apple.private.alloy.sms", SMSIncomingMessage),
|
||||
141: ("com.apple.private.alloy.sms", SMSIncomingImage),
|
||||
143: ("com.apple.private.alloy.sms", SMSReflectedMessage),
|
||||
144: ("com.apple.private.alloy.sms", SMSReflectedMessage),
|
||||
}
|
||||
|
||||
def maybe_decompress(message: bytes) -> bytes:
|
||||
"""Decompresses a message if it is compressed, otherwise returns the original message"""
|
||||
try:
|
||||
message = gzip.decompress(message)
|
||||
except:
|
||||
pass
|
||||
return message
|
||||
|
||||
class iMessageUser:
|
||||
"""Represents a logged in and connected iMessage user.
|
||||
This abstraction should probably be reworked into IDS some time..."""
|
||||
@ -434,27 +485,12 @@ class iMessageUser:
|
||||
"""
|
||||
Will return the next iMessage in the queue, or None if there are no messages
|
||||
"""
|
||||
|
||||
# Check for iMessages
|
||||
body = self._receive_raw(100, "com.apple.madrid")
|
||||
t = iMessage
|
||||
if body is None:
|
||||
# Check for SMS messages
|
||||
body = self._receive_raw(143, "com.apple.private.alloy.sms")
|
||||
t = SMSReflectedMessage
|
||||
if body is None:
|
||||
# Check for SMS reflected images
|
||||
body = self._receive_raw(144, "com.apple.private.alloy.sms")
|
||||
t = SMSReflectedMessage
|
||||
if body is None:
|
||||
# Check for SMS incoming messages
|
||||
body = self._receive_raw(140, "com.apple.private.alloy.sms")
|
||||
t = SMSIncomingMessage
|
||||
if body is None:
|
||||
# Incoming images
|
||||
body = self._receive_raw(141, "com.apple.private.alloy.sms")
|
||||
t = SMSIncomingImage
|
||||
if body is None:
|
||||
for type, (topic, cls) in MESSAGE_TYPES.items():
|
||||
body = self._receive_raw(type, topic)
|
||||
if body is not None:
|
||||
t = cls
|
||||
break
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
@ -485,8 +521,9 @@ class iMessageUser:
|
||||
self.USER_CACHE = {}
|
||||
|
||||
# Check to see if we have cached the keys for all of the participants
|
||||
if all([p in self.USER_CACHE for p in participants]):
|
||||
return
|
||||
#if all([p in self.USER_CACHE for p in participants]):
|
||||
# return
|
||||
# TODO: This doesn't work since it doesn't check if they are cached for all topics
|
||||
|
||||
# Look up the public keys for the participants, and cache a token : public key mapping
|
||||
lookup = self.user.lookup(participants, topic=topic)
|
||||
@ -625,6 +662,16 @@ class iMessageUser:
|
||||
if act_message is None:
|
||||
return False
|
||||
|
||||
logger.info(f"Received SMS activation message : {act_message}")
|
||||
# Decrypt the payload
|
||||
act_message = self._decrypt_payload(act_message["P"])
|
||||
act_message = plistlib.loads(maybe_decompress(act_message))
|
||||
|
||||
if act_message == {'wc': False, 'ar': True}:
|
||||
logger.info("SMS forwarding activated, sending response")
|
||||
else:
|
||||
logger.info("SMS forwarding de-activated, sending response")
|
||||
|
||||
self._send_raw(
|
||||
147,
|
||||
[self.user.current_handle],
|
||||
@ -634,17 +681,26 @@ class iMessageUser:
|
||||
}
|
||||
)
|
||||
|
||||
def send(self, message: "iMessage"):
|
||||
self._cache_keys(message.participants, "com.apple.madrid")
|
||||
def send(self, message: Message):
|
||||
# Check what type of message we are sending
|
||||
for t, (topic, cls) in MESSAGE_TYPES.items():
|
||||
if isinstance(message, cls):
|
||||
break
|
||||
else:
|
||||
raise Exception("Unknown message type")
|
||||
|
||||
send_to = message.participants if isinstance(message, iMessage) else [self.user.current_handle]
|
||||
|
||||
self._cache_keys(send_to, topic)
|
||||
|
||||
self._send_raw(
|
||||
100,
|
||||
message.participants,
|
||||
"com.apple.madrid",
|
||||
t,
|
||||
send_to,
|
||||
topic,
|
||||
message.to_raw(),
|
||||
message.id,
|
||||
{
|
||||
"E": "pair",
|
||||
"E": "pair", # TODO: Do we need the nr field for SMS?
|
||||
}
|
||||
)
|
||||
|
||||
@ -655,14 +711,14 @@ class iMessageUser:
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
for p in message.participants:
|
||||
for p in send_to:
|
||||
for t in self.USER_CACHE[p]:
|
||||
if t == self.connection.token:
|
||||
continue
|
||||
total += 1
|
||||
|
||||
while count < total and time.time() - start < 2:
|
||||
resp = self._receive_raw(255, "com.apple.madrid")
|
||||
resp = self._receive_raw(255, topic)
|
||||
if resp is None:
|
||||
continue
|
||||
count += 1
|
||||
|
Loading…
Reference in New Issue
Block a user