python-terminusgps 1.10.1__tar.gz → 1.10.3__tar.gz
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.
Potentially problematic release.
This version of python-terminusgps might be problematic. Click here for more details.
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/PKG-INFO +1 -1
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/pyproject.toml +1 -1
- python_terminusgps-1.10.3/terminusgps/aws/ses.py +72 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/twilio/caller.py +5 -6
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/items/base.py +9 -2
- python_terminusgps-1.10.3/terminusgps/wialon/items/notification.py +33 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/items/unit.py +32 -12
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/uv.lock +1 -1
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/.gitignore +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/COPYING +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/README.md +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/__init__.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/authorizenet/__init__.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/authorizenet/auth.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/authorizenet/profiles/__init__.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/authorizenet/profiles/addresses.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/authorizenet/profiles/base.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/authorizenet/profiles/customers.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/authorizenet/profiles/payments.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/aws/__init__.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/aws/secrets.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/settings.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/twilio/__init__.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/__init__.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/constants.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/errors.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/flags.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/items/__init__.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/items/resource.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/items/retranslator.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/items/route.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/items/unit_group.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/items/user.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/session.py +0 -0
- {python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-terminusgps
|
|
3
|
-
Version: 1.10.
|
|
3
|
+
Version: 1.10.3
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-terminusgps"
|
|
3
|
-
version = "1.10.
|
|
3
|
+
version = "1.10.3"
|
|
4
4
|
description = "Provides abstractions/utilities for working with Wialon API, Authorize.NET API, AWS API, and more."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [ {name = "Blake Nall", email = "blake@terminusgps.com" } ]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import boto3
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class SESEmailTemplate:
|
|
6
|
+
def __init__(self, template_name: str, region_name: str = "us-east-1") -> None:
|
|
7
|
+
self.name = template_name
|
|
8
|
+
self.region = region_name
|
|
9
|
+
self.client = boto3.Session().client(service_name="ses")
|
|
10
|
+
|
|
11
|
+
def send(
|
|
12
|
+
self,
|
|
13
|
+
from_addr: str,
|
|
14
|
+
recipients: list[str],
|
|
15
|
+
replyto_list: list[str],
|
|
16
|
+
data: dict[str, str],
|
|
17
|
+
cc_list: list[str] | None = None,
|
|
18
|
+
bcc_list: list[str] | None = None,
|
|
19
|
+
) -> None:
|
|
20
|
+
destination = self._get_destination(recipients, cc_list, bcc_list)
|
|
21
|
+
self.client.send_templated_email(
|
|
22
|
+
**{
|
|
23
|
+
"Source": from_addr,
|
|
24
|
+
"Destination": destination,
|
|
25
|
+
"ReplyToAddresses": replyto_list,
|
|
26
|
+
"Template": self.name,
|
|
27
|
+
"TemplateData": json.dumps(data),
|
|
28
|
+
}
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
def create(self, subject: str, text_content: str, html_content: str) -> None:
|
|
32
|
+
self.client.create_template(
|
|
33
|
+
**{
|
|
34
|
+
"Template": {
|
|
35
|
+
"TemplateName": self.name,
|
|
36
|
+
"SubjectPart": subject,
|
|
37
|
+
"TextPart": text_content,
|
|
38
|
+
"HtmlPart": html_content,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def update(self, subject: str, text_content: str, html_content: str) -> None:
|
|
44
|
+
self.client.update_template(
|
|
45
|
+
**{
|
|
46
|
+
"Template": {
|
|
47
|
+
"TemplateName": self.name,
|
|
48
|
+
"SubjectPart": subject,
|
|
49
|
+
"TextPart": text_content,
|
|
50
|
+
"HtmlPart": html_content,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def test_render(self, data: dict[str, str]) -> str:
|
|
56
|
+
response = self.client.test_render_template(
|
|
57
|
+
**{"TemplateName": self.name, "TemplateData": json.dumps(data)}
|
|
58
|
+
)
|
|
59
|
+
return response.get("RenderedTemplate")
|
|
60
|
+
|
|
61
|
+
def _get_destination(
|
|
62
|
+
self,
|
|
63
|
+
recipients: list[str],
|
|
64
|
+
cc_list: list[str] | None,
|
|
65
|
+
bcc_list: list[str] | None,
|
|
66
|
+
) -> dict[str, list[str]]:
|
|
67
|
+
destination: dict[str, list[str]] = {"ToAddresses": recipients}
|
|
68
|
+
if cc_list is not None:
|
|
69
|
+
destination.update({"CcAddresses": cc_list})
|
|
70
|
+
if bcc_list is not None:
|
|
71
|
+
destination.update({"BccAddresses": bcc_list})
|
|
72
|
+
return destination
|
|
@@ -9,14 +9,14 @@ from twilio.http.async_http_client import AsyncTwilioHttpClient
|
|
|
9
9
|
|
|
10
10
|
class TwilioCaller:
|
|
11
11
|
def __init__(self) -> None:
|
|
12
|
+
self.client_sid = settings.TWILIO_SID
|
|
13
|
+
self.client_token = settings.TWILIO_TOKEN
|
|
12
14
|
self.from_number = settings.TWILIO_FROM_NUMBER
|
|
13
|
-
self.
|
|
15
|
+
self.messaging_sid = settings.TWILIO_MESSAGING_SID
|
|
14
16
|
|
|
15
17
|
def __enter__(self) -> "TwilioCaller":
|
|
16
18
|
self.client = twilio.rest.Client(
|
|
17
|
-
|
|
18
|
-
settings.TWILIO_TOKEN,
|
|
19
|
-
http_client=AsyncTwilioHttpClient(),
|
|
19
|
+
self.client_sid, self.client_token, http_client=AsyncTwilioHttpClient()
|
|
20
20
|
)
|
|
21
21
|
return self
|
|
22
22
|
|
|
@@ -37,7 +37,6 @@ class TwilioCaller:
|
|
|
37
37
|
)
|
|
38
38
|
case _:
|
|
39
39
|
raise ValueError(f"Unsupported TwilioCaller method '{method}'.")
|
|
40
|
-
|
|
41
40
|
return task
|
|
42
41
|
|
|
43
42
|
async def create_call(self, to_number: str, message: str) -> None:
|
|
@@ -52,5 +51,5 @@ class TwilioCaller:
|
|
|
52
51
|
to=to_number,
|
|
53
52
|
from_=self.from_number,
|
|
54
53
|
body=message,
|
|
55
|
-
messaging_service_sid=self.
|
|
54
|
+
messaging_service_sid=self.messaging_sid,
|
|
56
55
|
)
|
|
@@ -5,7 +5,14 @@ from terminusgps.wialon.session import WialonSession
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class WialonBase:
|
|
8
|
-
def __init__(
|
|
8
|
+
def __init__(
|
|
9
|
+
self,
|
|
10
|
+
id: str | int | None = None,
|
|
11
|
+
session: WialonSession | None = None,
|
|
12
|
+
**kwargs,
|
|
13
|
+
) -> None:
|
|
14
|
+
if session is None:
|
|
15
|
+
raise ValueError("A valid Wialon API session is required.")
|
|
9
16
|
if isinstance(id, str) and not id.isdigit():
|
|
10
17
|
raise ValueError(f"'id' must be a digit. Got '{id}'.")
|
|
11
18
|
|
|
@@ -59,7 +66,7 @@ class WialonBase:
|
|
|
59
66
|
return True if self.id in response.keys() else False
|
|
60
67
|
|
|
61
68
|
@abstractmethod
|
|
62
|
-
def create(self) -> int | None:
|
|
69
|
+
def create(self, *args, **kwargs) -> int | None:
|
|
63
70
|
"""Creates a Wialon object and returns its id."""
|
|
64
71
|
raise NotImplementedError("Subclasses must implement this method.")
|
|
65
72
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from terminusgps.wialon.items.base import WialonBase
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class WialonNotification(WialonBase):
|
|
5
|
+
def create(
|
|
6
|
+
self,
|
|
7
|
+
resource_id: str | int,
|
|
8
|
+
name: str,
|
|
9
|
+
activation_time: int,
|
|
10
|
+
deactivation_time: int,
|
|
11
|
+
text: str | None = None,
|
|
12
|
+
max_alarms: int = 0,
|
|
13
|
+
interval: int = 0,
|
|
14
|
+
lang: str = "en",
|
|
15
|
+
) -> int | None:
|
|
16
|
+
if isinstance(resource_id, str) and not resource_id.isdigit():
|
|
17
|
+
raise ValueError(f"'resource_id' must be a digit, got '{resource_id}'.")
|
|
18
|
+
|
|
19
|
+
response = self.session.wialon_api.resource_update_notification(
|
|
20
|
+
**{
|
|
21
|
+
"itemId": resource_id,
|
|
22
|
+
"id": 0,
|
|
23
|
+
"callMode": "create",
|
|
24
|
+
"n": name,
|
|
25
|
+
"txt": text if text else name,
|
|
26
|
+
"ta": activation_time,
|
|
27
|
+
"td": deactivation_time,
|
|
28
|
+
"ma": max_alarms,
|
|
29
|
+
"mmtd": interval,
|
|
30
|
+
"la": lang,
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
return int(response[0].get("id")) if response else None
|
|
@@ -144,9 +144,9 @@ class WialonUnit(WialonBase):
|
|
|
144
144
|
|
|
145
145
|
def get_phone_numbers(self) -> list[str]:
|
|
146
146
|
"""
|
|
147
|
-
Retrieves all phone numbers assigned to
|
|
147
|
+
Retrieves all phone numbers assigned to the unit.
|
|
148
148
|
|
|
149
|
-
This includes any attached drivers, custom fields,
|
|
149
|
+
This includes any attached drivers, custom/admin fields, or otherwise assigned phone numbers.
|
|
150
150
|
|
|
151
151
|
:raises WialonError: If something goes wrong with Wialon.
|
|
152
152
|
:returns: A list of phone numbers.
|
|
@@ -154,28 +154,48 @@ class WialonUnit(WialonBase):
|
|
|
154
154
|
|
|
155
155
|
"""
|
|
156
156
|
|
|
157
|
-
phone_numbers = []
|
|
158
|
-
phones_0 = self._get_driver_phone_numbers()
|
|
159
|
-
phones_1 = self._get_cfield_phone_numbers()
|
|
157
|
+
phone_numbers: list[str] = []
|
|
158
|
+
phones_0: list[str] | None = self._get_driver_phone_numbers()
|
|
159
|
+
phones_1: list[str] | None = self._get_cfield_phone_numbers()
|
|
160
|
+
phones_2: list[str] | None = self._get_afield_phone_numbers()
|
|
160
161
|
|
|
161
|
-
if phones_0:
|
|
162
|
+
if phones_0 is not None:
|
|
162
163
|
phone_numbers.extend(phones_0)
|
|
163
|
-
if phones_1:
|
|
164
|
+
if phones_1 is not None:
|
|
164
165
|
phone_numbers.extend(phones_1)
|
|
166
|
+
if phones_2 is not None:
|
|
167
|
+
phone_numbers.extend(phones_2)
|
|
165
168
|
return list(dict.fromkeys(phone_numbers)) # Removes duplicate phone numbers
|
|
166
169
|
|
|
167
|
-
def
|
|
170
|
+
def _get_afield_phone_numbers(self, key: str = "to_number") -> list[str] | None:
|
|
168
171
|
"""
|
|
169
|
-
Retrives any phone numbers saved in
|
|
172
|
+
Retrives any phone numbers saved in an admin field by key.
|
|
170
173
|
|
|
174
|
+
:param key: An admin field key. Default is ``"to_number"``.
|
|
175
|
+
:type key: :py:obj:`str`
|
|
176
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
177
|
+
:returns: A list of phone numbers, if the unit has admin phone number fields.
|
|
178
|
+
:rtype: :py:obj:`list` | :py:obj:`None`
|
|
179
|
+
|
|
180
|
+
"""
|
|
181
|
+
for field_name, field_val in self.afields.items():
|
|
182
|
+
if field_name == key:
|
|
183
|
+
return self.clean_phone_numbers([field_val])
|
|
184
|
+
|
|
185
|
+
def _get_cfield_phone_numbers(self, key: str = "to_number") -> list[str] | None:
|
|
186
|
+
"""
|
|
187
|
+
Retrives any phone numbers saved in a custom field by key.
|
|
188
|
+
|
|
189
|
+
:param key: A custom field key. Default is ``"to_number"``.
|
|
190
|
+
:type key: :py:obj:`str`
|
|
171
191
|
:raises WialonError: If something goes wrong with Wialon.
|
|
172
192
|
:returns: A list of phone numbers, if the unit has custom phone number fields.
|
|
173
193
|
:rtype: :py:obj:`list` | :py:obj:`None`
|
|
174
194
|
|
|
175
195
|
"""
|
|
176
|
-
for
|
|
177
|
-
if
|
|
178
|
-
return self.clean_phone_numbers([
|
|
196
|
+
for field_name, field_val in self.cfields.items():
|
|
197
|
+
if field_name == key:
|
|
198
|
+
return self.clean_phone_numbers([field_val])
|
|
179
199
|
|
|
180
200
|
def _get_driver_phone_numbers(self) -> list[str] | None:
|
|
181
201
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/authorizenet/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/authorizenet/profiles/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/items/__init__.py
RENAMED
|
File without changes
|
{python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/items/resource.py
RENAMED
|
File without changes
|
{python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/items/retranslator.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.10.1 → python_terminusgps-1.10.3}/terminusgps/wialon/items/unit_group.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|