python-terminusgps 1.9.9__py3-none-any.whl → 1.10.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-terminusgps
3
- Version: 1.9.9
3
+ Version: 1.10.0
4
4
  Summary: Provides abstractions/utilities for working with Wialon API, Authorize.NET API, AWS API, and more.
5
5
  Project-URL: Documentation, https://app.terminusgps.com/docs/apps/python-terminusgps/index.html
6
6
  Project-URL: Repository, https://github.com/terminusgps/python-terminusgps
@@ -17,3 +17,4 @@ Requires-Dist: authorizenet>=1.1.5
17
17
  Requires-Dist: boto3>=1.34.144
18
18
  Requires-Dist: django>=5.1.5
19
19
  Requires-Dist: python-wialon>=1.2.4
20
+ Requires-Dist: twilio>=9.4.5
@@ -1,5 +1,5 @@
1
1
  terminusgps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- terminusgps/settings.py,sha256=Mdeuo6ghfW28QVrBqe5mwwX2_Lk79fJ5kLfR9LV7zZM,314
2
+ terminusgps/settings.py,sha256=JMcMFqNQRIcljIZrEsU9pm9AhxG-gcnDC7EONKd3ShE,502
3
3
  terminusgps/authorizenet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  terminusgps/authorizenet/auth.py,sha256=kWsqRT9OVEAQuNxDzQNzY1x2SqmvJr-HAbLwgkILntk,997
5
5
  terminusgps/authorizenet/profiles/__init__.py,sha256=QKjMKcXpCSCEhv6LBCz0yGP8t0VxAyKyYRS4_HLYnxQ,114
@@ -9,6 +9,8 @@ terminusgps/authorizenet/profiles/customers.py,sha256=iEuNFP6PHuGdFQftgxxKpQFYaG
9
9
  terminusgps/authorizenet/profiles/payments.py,sha256=qOWp-gO6qBCADP98WjoNCHm-jtq7DY5-moiPsOnT5yI,5263
10
10
  terminusgps/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  terminusgps/aws/secrets.py,sha256=kgRA77rs0mD4berWRLkPtJLOe4Grf--o5f8NzwQqXCk,360
12
+ terminusgps/twilio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ terminusgps/twilio/caller.py,sha256=VQecBgi-rI9UwHjz5RzyVdtkuNB52ftmcfIqymh0guk,2280
12
14
  terminusgps/wialon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
15
  terminusgps/wialon/constants.py,sha256=aybYcNcHyar2lz_6BlQbMWpbcHW6eyJeq05QwuiqZQ0,3078
14
16
  terminusgps/wialon/errors.py,sha256=SV9pVwU6FZ_zGlGP6zJN6aLE2auF4TfHFISQLiPMKrI,1758
@@ -23,7 +25,7 @@ terminusgps/wialon/items/route.py,sha256=qOHPN_rejwiGqvwWzlwmUIAIyc3lKavCalf8ki6
23
25
  terminusgps/wialon/items/unit.py,sha256=mEYQRpICELQPR3dyDJVRzoKeIuFRnPgkqK-Oo6xuIP4,6306
24
26
  terminusgps/wialon/items/unit_group.py,sha256=1yc7ldPIgGbtiTj0djRDWmt6Q9K_VT9sxOaioasbbLY,5212
25
27
  terminusgps/wialon/items/user.py,sha256=bkcMw_YiocaMuhP_pBfB7apjAZwnsOzGScnGkn8Ybbw,6107
26
- python_terminusgps-1.9.9.dist-info/METADATA,sha256=tbP74Vv0X3nKIuyECKlcHHKVsoQJ4mp4BHRsP1Rj7V4,882
27
- python_terminusgps-1.9.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
28
- python_terminusgps-1.9.9.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
29
- python_terminusgps-1.9.9.dist-info/RECORD,,
28
+ python_terminusgps-1.10.0.dist-info/METADATA,sha256=dPXjLEr-PHdgIL2lWYevYO4FhHwjk-DcwhxyXGXbQys,912
29
+ python_terminusgps-1.10.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
30
+ python_terminusgps-1.10.0.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
31
+ python_terminusgps-1.10.0.dist-info/RECORD,,
terminusgps/settings.py CHANGED
@@ -1,8 +1,12 @@
1
- from os import getenv
1
+ import os
2
2
 
3
3
  DEBUG = True
4
+ MERCHANT_AUTH_LOGIN_ID = os.getenv("MERCHANT_AUTH_LOGIN_ID")
5
+ MERCHANT_AUTH_TRANSACTION_KEY = os.getenv("MERCHANT_AUTH_TRANSACTION_KEY")
4
6
  SECRET_KEY = "xem*6no%8d9%^qzt2f3x3ar-uq4_+7h9myc$t0!+4%bj5us6f)"
5
- WIALON_ADMIN_ID = getenv("WIALON_ADMIN_ID")
6
- WIALON_TOKEN = getenv("WIALON_TOKEN")
7
- MERCHANT_AUTH_LOGIN_ID = getenv("MERCHANT_AUTH_LOGIN_ID")
8
- MERCHANT_AUTH_TRANSACTION_KEY = getenv("MERCHANT_AUTH_TRANSACTION_KEY")
7
+ TWILIO_FROM_NUMBER = os.getenv("TWILIO_FROM_NUMBER")
8
+ TWILIO_MESSAGING_SID = os.getenv("TWILIO_MESSAGING_SID")
9
+ TWILIO_SID = os.getenv("TWILIO_SID")
10
+ TWILIO_TOKEN = os.getenv("TWILIO_TOKEN")
11
+ WIALON_ADMIN_ID = os.getenv("WIALON_ADMIN_ID")
12
+ WIALON_TOKEN = os.getenv("WIALON_TOKEN")
File without changes
@@ -0,0 +1,65 @@
1
+ from typing import Any
2
+
3
+ import asyncio
4
+ import twilio.rest
5
+
6
+ from django.conf import settings, ImproperlyConfigured
7
+ from twilio.http.async_http_client import AsyncTwilioHttpClient
8
+
9
+ if not hasattr(settings, "TWILIO_FROM_NUMBER"):
10
+ raise ImproperlyConfigured("'TWILIO_FROM_NUMBER' setting is required.")
11
+ if not hasattr(settings, "TWILIO_MESSAGING_SID"):
12
+ raise ImproperlyConfigured("'TWILIO_MESSAGING_SID' setting is required.")
13
+ if not hasattr(settings, "TWILIO_SID"):
14
+ raise ImproperlyConfigured("'TWILIO_SID' setting is required.")
15
+ if not hasattr(settings, "TWILIO_TOKEN"):
16
+ raise ImproperlyConfigured("'TWILIO_TOKEN' setting is required.")
17
+
18
+
19
+ class TwilioCaller:
20
+ def __init__(self) -> None:
21
+ self.from_number = settings.TWILIO_FROM_NUMBER
22
+ self.messaging_service_sid = settings.TWILIO_MESSAGING_SID
23
+
24
+ def __enter__(self) -> "TwilioCaller":
25
+ self.client = twilio.rest.Client(
26
+ settings.TWILIO_SID,
27
+ settings.TWILIO_TOKEN,
28
+ http_client=AsyncTwilioHttpClient(),
29
+ )
30
+ return self
31
+
32
+ def __exit__(self, exc_type, exc_value, exc_tb) -> None:
33
+ return None
34
+
35
+ async def create_notification(
36
+ self, to_number: str, message: str, method: str = "sms"
37
+ ) -> asyncio.Task[Any]:
38
+ match method:
39
+ case "sms":
40
+ task = asyncio.create_task(
41
+ self.create_sms(to_number=to_number, message=message)
42
+ )
43
+ case "call" | "phone":
44
+ task = asyncio.create_task(
45
+ self.create_call(to_number=to_number, message=message)
46
+ )
47
+ case _:
48
+ raise ValueError(f"Unsupported TwilioCaller method '{method}'.")
49
+
50
+ return task
51
+
52
+ async def create_call(self, to_number: str, message: str) -> None:
53
+ await self.client.calls.create_async(
54
+ to=to_number,
55
+ from_=self.from_number,
56
+ twiml=f"<Response><Say>{message}</Say></Response>",
57
+ )
58
+
59
+ async def create_sms(self, to_number: str, message: str) -> None:
60
+ await self.client.messages.create_async(
61
+ to=to_number,
62
+ from_=self.from_number,
63
+ body=message,
64
+ messaging_service_sid=self.messaging_service_sid,
65
+ )