From ad285fae6de18fc786051f725d68340539c8e2d9 Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Mon, 24 Aug 2020 14:16:07 +0200 Subject: trying with pysignald HEAD --- .gitmodules | 3 + libs/pysignald | 1 + main.py | 5 +- pysignald/__init__.py | 4 - pysignald/__pycache__/__init__.cpython-37.pyc | Bin 203 -> 0 bytes pysignald/__pycache__/main.cpython-37.pyc | Bin 6450 -> 0 bytes pysignald/__pycache__/types.cpython-37.pyc | Bin 935 -> 0 bytes pysignald/main.py | 212 -------------------------- pysignald/types.py | 24 --- 9 files changed, 6 insertions(+), 243 deletions(-) create mode 100644 .gitmodules create mode 160000 libs/pysignald delete mode 100644 pysignald/__init__.py delete mode 100644 pysignald/__pycache__/__init__.cpython-37.pyc delete mode 100644 pysignald/__pycache__/main.cpython-37.pyc delete mode 100644 pysignald/__pycache__/types.cpython-37.pyc delete mode 100644 pysignald/main.py delete mode 100644 pysignald/types.py diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..aaac766 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libs/pysignald"] + path = libs/pysignald + url = git@gitlab.com:stavros/pysignald.git diff --git a/libs/pysignald b/libs/pysignald new file mode 160000 index 0000000..e87b2ec --- /dev/null +++ b/libs/pysignald @@ -0,0 +1 @@ +Subproject commit e87b2ece9255205bee339287bac6c13996ed32a4 diff --git a/main.py b/main.py index d883eff..fd3cd3b 100755 --- a/main.py +++ b/main.py @@ -3,10 +3,9 @@ import os import sys import getopt -import json import requests -from signald import Signal +from .libs.pysignald.signald import Signal from configparser import ConfigParser @@ -46,7 +45,7 @@ def startup(number): # TODO: try catch response = requests.post('http://localhost:18080', - json={"command": match.group(1), "arguments": strip(match.group(2))}) + json={"command": match.group(1), "arguments": match.group(2).strip()}) answer = "" replies = response.json()['reply'] diff --git a/pysignald/__init__.py b/pysignald/__init__.py deleted file mode 100644 index 959fbf5..0000000 --- a/pysignald/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# flake8: noqa -__version__ = "0.0.6" - -from .main import Signal diff --git a/pysignald/__pycache__/__init__.cpython-37.pyc b/pysignald/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index dc56638..0000000 Binary files a/pysignald/__pycache__/__init__.cpython-37.pyc and /dev/null differ diff --git a/pysignald/__pycache__/main.cpython-37.pyc b/pysignald/__pycache__/main.cpython-37.pyc deleted file mode 100644 index 3325cc3..0000000 Binary files a/pysignald/__pycache__/main.cpython-37.pyc and /dev/null differ diff --git a/pysignald/__pycache__/types.cpython-37.pyc b/pysignald/__pycache__/types.cpython-37.pyc deleted file mode 100644 index 20b838c..0000000 Binary files a/pysignald/__pycache__/types.cpython-37.pyc and /dev/null differ diff --git a/pysignald/main.py b/pysignald/main.py deleted file mode 100644 index cfaa79c..0000000 --- a/pysignald/main.py +++ /dev/null @@ -1,212 +0,0 @@ -import json -import random -import re -import socket -from typing import Iterator, List # noqa - -from .types import Attachment, Message - -# We'll need to know the compiled RE object later. -RE_TYPE = type(re.compile("")) - - -def readlines(s: socket.socket) -> Iterator[bytes]: - "Read a socket, line by line." - buf = [] # type: List[bytes] - while True: - char = s.recv(1) - if not char: - raise ConnectionResetError("connection was reset") - - if char == b"\n": - yield b"".join(buf) - buf = [] - else: - buf.append(char) - - -class Signal: - def __init__(self, username, socket_path="/var/run/signald/signald.sock"): - self.username = username - self.socket_path = socket_path - self._chat_handlers = [] - - def _get_id(self): - "Generate a random ID." - return "".join(random.choice("abcdefghijklmnopqrstuvwxyz0123456789") for _ in range(10)) - - def _get_socket(self) -> socket.socket: - "Create a socket, connect to the server and return it." - - # Support TCP sockets on the sly. - if isinstance(self.socket_path, tuple): - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - else: - s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - s.connect(self.socket_path) - return s - - def _send_command(self, payload: dict, block: bool = False): - s = self._get_socket() - msg_id = self._get_id() - payload["id"] = msg_id - s.recv(1024) # Flush the buffer. - s.send(json.dumps(payload).encode("utf8") + b"\n") - - if not block: - return - - response = s.recv(4 * 1024) - for line in response.split(b"\n"): - if msg_id.encode("utf8") not in line: - continue - - data = json.loads(line) - - if data.get("id") != msg_id: - continue - - if data["type"] == "unexpected_error": - raise ValueError("unexpected error occurred: " + str(line)) - - def register(self, voice=False): - """ - Register the given number. - - voice: Whether to receive a voice call or an SMS for verification. - """ - payload = {"type": "register", "username": self.username, "voice": voice} - self._send_command(payload) - - def verify(self, code: str): - """ - Verify the given number by entering the code you received. - - code: The code Signal sent you. - """ - payload = {"type": "verify", "username": self.username, "code": code} - self._send_command(payload) - - def receive_messages(self) -> Iterator[Message]: - "Keep returning received messages." - s = self._get_socket() - s.send(json.dumps({"type": "subscribe", "username": self.username}).encode("utf8") + b"\n") - - for line in readlines(s): - try: - message = json.loads(line.decode()) - except json.JSONDecodeError: - print("Invalid JSON") - - #print("type: " + message.get("type")) - if message.get("type") != "message": #or ( - #not message["data"]["isReceipt"] and message["data"].get("dataMessage") is None - #): - # If the message type isn't "message", or if it's a weird message whose - # purpose I don't know, return. I think the weird message is a typing - # notification. - continue - - message = message["data"] - data_message = message.get("dataMessage", {}) - - yield Message( - username=message["username"], - source=message["source"], - text=data_message.get("body"), - source_device=message["sourceDevice"], - timestamp=data_message.get("timestamp"), - timestamp_iso=message["timestampISO"], - expiration_secs=data_message.get("expiresInSeconds"), -# is_receipt=message["isReceipt"], - group_info=data_message.get("group", {}), - attachments=[ - Attachment( - content_type=attachment["contentType"], - id=attachment["id"], - size=attachment["size"], - stored_filename=attachment["storedFilename"], - ) - for attachment in data_message.get("attachments", []) - ], - ) - - def send_message(self, recipient: str, text: str, block: bool = True) -> None: - """ - Send a message. - - recipient: The recipient's phone number, in E.123 format. - text: The text of the message to send. - block: Whether to block while sending. If you choose not to block, you won't get an exception if there - are any errors. - """ - payload = {"type": "send", "username": self.username, "recipientAddress": recipient, "messageBody": text} -# print(f"payload: {payload}") - self._send_command(payload, block) - - def send_group_message(self, recipient_group_id: str, text: str, block: bool = False) -> None: - """ - Send a group message. - - recipient_group_id: The base64 encoded group ID to send to. - text: The text of the message to send. - block: Whether to block while sending. If you choose not to block, you won't get an exception if - there are any errors. - """ - payload = { - "type": "send", - "username": self.username, - "recipientGroupId": recipient_group_id, - "messageBody": text, - } - self._send_command(payload, block) - - def chat_handler(self, regex, order=100): - """ - A decorator that registers a chat handler function with a regex. - """ - if not isinstance(regex, RE_TYPE): - regex = re.compile(regex, re.I) - - def decorator(func): - self._chat_handlers.append((order, regex, func)) - # Use only the first value to sort so that declaration order doesn't change. - self._chat_handlers.sort(key=lambda x: x[0]) - return func - - return decorator - - def run_chat(self): - """ - Start the chat event loop. - """ - for message in self.receive_messages(): - if not message.text: - continue - #print("text: " + message.text) - for _, regex, func in self._chat_handlers: - match = re.search(regex, message.text) - if not match: - continue - - try: - reply = func(message, match) - except: # noqa - We don't care why this failed. - continue - - if isinstance(reply, tuple): - stop, reply = reply - else: - stop = True - - # In case a message came from a group chat - group_id = message.group_info.get("groupId") - - if group_id: - self.send_group_message(recipient_group_id=group_id, text=reply) - else: - self.send_message(recipient=message.source, text=reply) - - if stop: - # We don't want to continue matching things. - break diff --git a/pysignald/types.py b/pysignald/types.py deleted file mode 100644 index 1b605b3..0000000 --- a/pysignald/types.py +++ /dev/null @@ -1,24 +0,0 @@ -import attr - - -@attr.s -class Attachment: - content_type = attr.ib(type=str) - id = attr.ib(type=str) - size = attr.ib(type=int) - stored_filename = attr.ib(type=str) - - -@attr.s -class Message: - username = attr.ib(type=str) - source = attr.ib(type=str) - text = attr.ib(type=str) - source_device = attr.ib(type=int, default=0) - timestamp = attr.ib(type=int, default=None) - timestamp_iso = attr.ib(type=str, default=None) - expiration_secs = attr.ib(type=int, default=0) - is_receipt = attr.ib(type=bool, default=False) - attachments = attr.ib(type=list, default=[]) - quote = attr.ib(type=str, default=None) - group_info = attr.ib(type=dict, default={}) -- cgit v1.2.3-54-g00ecf