KdeConnect.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import subprocess
  2. import logging
  3. import re
  4. from pydantic import BaseModel
  5. class InvalidArgument(Exception):
  6. pass
  7. class InvalidDevice(Exception):
  8. pass
  9. class KDEConnectError(Exception):
  10. pass
  11. class KDEDevice(BaseModel):
  12. id: str
  13. name: str
  14. paired: bool
  15. reachable: bool
  16. class KDEConnect:
  17. device: KDEDevice
  18. def __init__(self, device_name=None, device_id=None):
  19. if device_name is None and device_id is None:
  20. raise InvalidArgument("device_name or device_id need to be provided")
  21. try:
  22. # Verify kdeconnect is available
  23. KDEConnect.run_kde_command(["-v"])
  24. except FileNotFoundError:
  25. raise KDEConnectError("KDEconnect-cli is not available on this computer")
  26. # verify the device exist
  27. devices = KDEConnect.get_device_list()
  28. device = None
  29. for d in devices:
  30. if (d.name == device_name) or (d.id == device_id):
  31. device = d
  32. break
  33. if device is None:
  34. raise InvalidDevice(f"No device found with id {device_id} or name {device_name}")
  35. if not device.paired:
  36. raise InvalidDevice(f"Device {device.name} is not paired with this computer")
  37. if not device.reachable:
  38. raise InvalidDevice(f"Device {device.name} is not reachable by this computer")
  39. self.device = device
  40. def send_sms(self, phone_number: str, sms_content: str):
  41. # Compact phone number by removing space
  42. phone = re.sub("[^+0-9]", "", phone_number)
  43. command = [
  44. "-d",
  45. self.device.id,
  46. "--send-sms",
  47. sms_content,
  48. "--destination",
  49. phone,
  50. ]
  51. KDEConnect.run_kde_command(command)
  52. @staticmethod
  53. def run_kde_command(args: list[str]) -> str:
  54. command: list[str] = ["kdeconnect-cli"]
  55. command.extend(args)
  56. process: CompletedProcess = subprocess.run(command, capture_output=True)
  57. subprocess_response = process.stdout.decode("utf-8")
  58. logging.debug("Subprocess call : \n>> " + " ".join(command) + "\n" + subprocess_response)
  59. if process.stderr != b"":
  60. error_msg: str = process.stderr.decode("utf-8")
  61. if error_msg.endswith("devices found\n"):
  62. logging.info(error_msg)
  63. else:
  64. raise KDEConnectError(error_msg)
  65. return subprocess_response
  66. @staticmethod
  67. def get_device_list() -> list[KDEDevice]:
  68. """Return the list of devices known by kde connect of this computer"""
  69. KDEConnect.run_kde_command(["--refresh"])
  70. output: list[KDEDevice] = []
  71. device_entries: list[str] = KDEConnect.run_kde_command(["-l"]).strip().split("\n")
  72. for device_str in device_entries:
  73. if device_str == "":
  74. continue
  75. result = re.search("^- ([^:]+): ([a-z0-9_]{36})", device_str)
  76. reachable = "reachable" in device_str
  77. paired = "paired" in device_str
  78. device = KDEDevice(
  79. name=result.group(1),
  80. id=result.group(2),
  81. reachable=reachable,
  82. paired=paired,
  83. )
  84. output.append(device)
  85. return output
  86. if __name__ == "__main__":
  87. kde = KDEConnect(device_name="Redmi 7A")
  88. kde.send_sms("0700000000", ("160" * 53) + "\n" + "b")
  89. kde.send_sms("0700000000", "162" * 54)
  90. kde.send_sms("0700000000", "simple message")
  91. kde.send_sms("+33700000000", "+33 number")
  92. kde.send_sms("+33 77 000 000 0", "spaced number")
  93. kde.send_sms("0700000000", "Multiline sms\nthis is a second line")
  94. kde.send_sms(
  95. "0700000000",
  96. """Lorem ipsum dolor sit amet,
  97. consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
  98. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
  99. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
  100. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.""",
  101. )