python-terminusgps 33.2.0__py3-none-any.whl → 33.3.1__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.
Potentially problematic release.
This version of python-terminusgps might be problematic. Click here for more details.
- {python_terminusgps-33.2.0.dist-info → python_terminusgps-33.3.1.dist-info}/METADATA +2 -1
- {python_terminusgps-33.2.0.dist-info → python_terminusgps-33.3.1.dist-info}/RECORD +8 -7
- terminusgps/authorizenet/tests/test_profiles.py +9 -3
- terminusgps/authorizenet/utils.py +97 -1
- terminusgps/aws/notifier.py +49 -0
- terminusgps/django/validators.py +93 -0
- terminusgps/aws/connect.py +0 -21
- {python_terminusgps-33.2.0.dist-info → python_terminusgps-33.3.1.dist-info}/WHEEL +0 -0
- {python_terminusgps-33.2.0.dist-info → python_terminusgps-33.3.1.dist-info}/licenses/COPYING +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-terminusgps
|
|
3
|
-
Version: 33.
|
|
3
|
+
Version: 33.3.1
|
|
4
4
|
Summary: Provides abstractions/utilities for working with Wialon API, Authorize.NET API, AWS API, and more.
|
|
5
5
|
Project-URL: Documentation, https://docs.terminusgps.com
|
|
6
6
|
Project-URL: Repository, https://github.com/terminusgps/python-terminusgps
|
|
@@ -12,6 +12,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.13
|
|
14
14
|
Requires-Python: >=3.12
|
|
15
|
+
Requires-Dist: aiobotocore>=2.21.1
|
|
15
16
|
Requires-Dist: argparse>=1.4.0
|
|
16
17
|
Requires-Dist: authorizenet>=1.1.5
|
|
17
18
|
Requires-Dist: boto3>=1.34.144
|
|
@@ -3,7 +3,7 @@ terminusgps/authorizenet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
3
3
|
terminusgps/authorizenet/auth.py,sha256=umNpOXObDrIt2K40padWBedQl7tVAmEg2alBWhGk-qQ,1238
|
|
4
4
|
terminusgps/authorizenet/constants.py,sha256=xmulPmiBLhFfZoc7Il3l-DZA9Nq5HSaJmJKU-v-5X-Y,420
|
|
5
5
|
terminusgps/authorizenet/controllers.py,sha256=9t62qdGpmAkP4tNyPefd7vBRutXvMWsxql6z_pg52Bg,2146
|
|
6
|
-
terminusgps/authorizenet/utils.py,sha256=
|
|
6
|
+
terminusgps/authorizenet/utils.py,sha256=FrKqXWrplcgiET1rDTmUaqmN_ze7j93jWgfFeJR8rlg,7073
|
|
7
7
|
terminusgps/authorizenet/profiles/__init__.py,sha256=IG4XCEEYtHKqXOatlZlob6J3ukAgF7cFR-RXxOSMS1c,161
|
|
8
8
|
terminusgps/authorizenet/profiles/addresses.py,sha256=xDlnFlIjuR7NVXwfj5aJT9E_GolnYFuYASkfenvWfm8,6292
|
|
9
9
|
terminusgps/authorizenet/profiles/base.py,sha256=lPc8Pugp5EcXtZmeBpeqicij7l0ROGvMYTV8J0fLLmQ,3768
|
|
@@ -12,16 +12,17 @@ terminusgps/authorizenet/profiles/payments.py,sha256=MmjvE4ZSfgyGPRUzeREB_dX_n6Q
|
|
|
12
12
|
terminusgps/authorizenet/profiles/subscriptions.py,sha256=m_jb9GqeD1tLmeqSnaGwJrzPcQOulEkF8K1wCaqKR24,7924
|
|
13
13
|
terminusgps/authorizenet/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
terminusgps/authorizenet/tests/test_auth.py,sha256=sdByYrcv8RKjcJckOHbyHH1z_M4qrATFI3qj_XDQXbk,1624
|
|
15
|
-
terminusgps/authorizenet/tests/test_profiles.py,sha256=
|
|
15
|
+
terminusgps/authorizenet/tests/test_profiles.py,sha256=tvLBY0iSAC33RlWiBP_NSnPskUQBjfrf0YHMpR-m22k,7566
|
|
16
16
|
terminusgps/authorizenet/tests/test_utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
terminusgps/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
terminusgps/aws/
|
|
18
|
+
terminusgps/aws/notifier.py,sha256=0w7tuMJ2tslMXKrLYcHi8kkxPsbvgfyFajkpD4UwlLc,1361
|
|
19
19
|
terminusgps/aws/secrets.py,sha256=MxQEmmBLpMUQ2tYAsHdCYf-7RZ84LiogdKcTsACX5dw,361
|
|
20
20
|
terminusgps/aws/utils.py,sha256=68GWcllu4h41qzFiKdUkWOAA4LDsTPqRY446VRMxYsY,116
|
|
21
21
|
terminusgps/django/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
terminusgps/django/mixins.py,sha256=Q9ZJuzpk3d9lDnlVA8ZTVvnZWxB13p08EQ8yVJcztn4,1034
|
|
23
23
|
terminusgps/django/settings.py,sha256=yJIcBE0xjY60AXF_gonY5hS3ofseqPW2k9uSoELgoho,639
|
|
24
24
|
terminusgps/django/utils.py,sha256=SYDQyHA5tTuVwdpZGsCtf0LpTTD0ilRKoxa8StfSTpQ,156
|
|
25
|
+
terminusgps/django/validators.py,sha256=dnENfniiHRJjZhQQ76dIcjfwuq-mkjQahKegZYgmryc,3342
|
|
25
26
|
terminusgps/django/forms/__init__.py,sha256=hh8Z9AC_u2m2bu3h6sdmPyndfQneCEVovENPHmoTDC0,21
|
|
26
27
|
terminusgps/django/forms/fields.py,sha256=BfuPzOZyGvWsEzONW2h4i01fhoL0IS0-gDdBKW4jHgI,2225
|
|
27
28
|
terminusgps/django/forms/forms.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -53,7 +54,7 @@ terminusgps/wialon/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
53
54
|
terminusgps/wialon/tests/test_items.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
55
|
terminusgps/wialon/tests/test_session.py,sha256=9mBlYchMo9NeqRIZsmxYzrM1zBHorqu4ooxqSNppLpI,1336
|
|
55
56
|
terminusgps/wialon/tests/test_utils.py,sha256=SK4PxJQGECFnzx_EQeRAQfsQ5_3FLaVcis2W9u_ibuI,1730
|
|
56
|
-
python_terminusgps-33.
|
|
57
|
-
python_terminusgps-33.
|
|
58
|
-
python_terminusgps-33.
|
|
59
|
-
python_terminusgps-33.
|
|
57
|
+
python_terminusgps-33.3.1.dist-info/METADATA,sha256=BoV05Kh_54bDSH1P82Pe7MhHm3j8OTqBMqwZiEMrC0w,1616
|
|
58
|
+
python_terminusgps-33.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
59
|
+
python_terminusgps-33.3.1.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
60
|
+
python_terminusgps-33.3.1.dist-info/RECORD,,
|
|
@@ -149,7 +149,9 @@ class PaymentProfileTestCase(TestCase):
|
|
|
149
149
|
def test_payment_profile_create(self) -> None:
|
|
150
150
|
"""Fails if a payment profile is not properly created in Authorizenet."""
|
|
151
151
|
test_payment_profile = PaymentProfile(
|
|
152
|
-
id=None,
|
|
152
|
+
id=None,
|
|
153
|
+
customer_profile_id=str(self.test_customer_profile.id),
|
|
154
|
+
default=True,
|
|
153
155
|
)
|
|
154
156
|
test_payment_profile.id = test_payment_profile.create(
|
|
155
157
|
address=self.test_address_obj, payment=self.test_payment_obj
|
|
@@ -159,7 +161,9 @@ class PaymentProfileTestCase(TestCase):
|
|
|
159
161
|
def test_payment_profile_delete(self) -> None:
|
|
160
162
|
"""Fails if a payment profile is not properly deleted in Authorizenet."""
|
|
161
163
|
test_payment_profile = PaymentProfile(
|
|
162
|
-
id=None,
|
|
164
|
+
id=None,
|
|
165
|
+
customer_profile_id=str(self.test_customer_profile.id),
|
|
166
|
+
default=True,
|
|
163
167
|
)
|
|
164
168
|
test_payment_profile.id = test_payment_profile.create(
|
|
165
169
|
address=self.test_address_obj, payment=self.test_payment_obj
|
|
@@ -170,7 +174,9 @@ class PaymentProfileTestCase(TestCase):
|
|
|
170
174
|
def test_payment_profile_last_4(self) -> None:
|
|
171
175
|
"""Fails if a payment profile's last 4 credit card digits are not properly retrieved."""
|
|
172
176
|
test_payment_profile = PaymentProfile(
|
|
173
|
-
id=None,
|
|
177
|
+
id=None,
|
|
178
|
+
customer_profile_id=str(self.test_customer_profile.id),
|
|
179
|
+
default=True,
|
|
174
180
|
)
|
|
175
181
|
test_payment_profile.id = test_payment_profile.create(
|
|
176
182
|
address=self.test_address_obj, payment=self.test_payment_obj
|
|
@@ -5,11 +5,107 @@ from .auth import get_merchant_auth
|
|
|
5
5
|
from .controllers import AuthorizenetControllerExecutor
|
|
6
6
|
|
|
7
7
|
|
|
8
|
+
def get_payment_profile_transactions(
|
|
9
|
+
customer_profile_id: int | str,
|
|
10
|
+
payment_profile_id: int | str,
|
|
11
|
+
descending: bool = False,
|
|
12
|
+
limit: int = 100,
|
|
13
|
+
offset: int = 0,
|
|
14
|
+
) -> dict | None:
|
|
15
|
+
"""
|
|
16
|
+
Returns a transaction list for a customer payment profile.
|
|
17
|
+
|
|
18
|
+
`getTransactionListForCustomerRequest <https://developer.authorize.net/api/reference/index.html#transaction-reporting-get-customer-profile-transaction-list>`_
|
|
19
|
+
|
|
20
|
+
:param customer_profile_id: A customer profile id.
|
|
21
|
+
:type customer_profile_id: :py:obj:`int` | :py:obj:`str`
|
|
22
|
+
:param payment_profile_id: A customer payment profile id.
|
|
23
|
+
:type payment_profile_id: :py:obj:`int` | :py:obj:`str`
|
|
24
|
+
:param descending: Whether or not to sort the response in descending order. Default is :py:obj:`False`.
|
|
25
|
+
:type descending: :py:obj:`bool`
|
|
26
|
+
:param limit: Maximum amount of transactions to return in the response. Default is :py:obj:`100` .
|
|
27
|
+
:type limit: :py:obj:`int`
|
|
28
|
+
:param offset: Offsets the response for pagination. Default is :py:obj:`0` for page 0.
|
|
29
|
+
:type offset: :py:obj:`int`
|
|
30
|
+
:raises ValueError: If ``customer_profile_id`` was provided as a string containing non-digits.
|
|
31
|
+
:raises ValueError: If ``payment_profile_id`` was provided as a string containing non-digits.
|
|
32
|
+
:raises AuthorizenetControllerExecutionError: If the API call fails.
|
|
33
|
+
:returns: A merchant details object, if found.
|
|
34
|
+
:rtype: :py:obj:`dict` | :py:obj:`None`
|
|
35
|
+
|
|
36
|
+
"""
|
|
37
|
+
raise NotImplementedError
|
|
38
|
+
|
|
39
|
+
if isinstance(customer_profile_id, str) and not customer_profile_id.isdigit():
|
|
40
|
+
raise ValueError(
|
|
41
|
+
f"'customer_profile_id' can only contain digits, got '{customer_profile_id}'."
|
|
42
|
+
)
|
|
43
|
+
if isinstance(payment_profile_id, str) and not payment_profile_id.isdigit():
|
|
44
|
+
raise ValueError(
|
|
45
|
+
f"'payment_profile_id' can only contain digits, got '{payment_profile_id}'."
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
request = apicontractsv1.getTransactionListForCustomerRequest(
|
|
49
|
+
merchantAuthentication=get_merchant_auth(),
|
|
50
|
+
customerProfileId=str(customer_profile_id),
|
|
51
|
+
customerPaymentProfileId=str(payment_profile_id),
|
|
52
|
+
sorting={
|
|
53
|
+
"orderBy": "submitTimeUTC",
|
|
54
|
+
"orderDescending": str(descending).lower(),
|
|
55
|
+
},
|
|
56
|
+
paging={"limit": limit, "offset": offset},
|
|
57
|
+
)
|
|
58
|
+
controller = apicontrollers.getTransactionListForCustomerController(request)
|
|
59
|
+
return AuthorizenetControllerExecutor.execute_controller(controller)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_merchant_details() -> dict | None:
|
|
63
|
+
"""
|
|
64
|
+
Returns Authorizenet merchant details.
|
|
65
|
+
|
|
66
|
+
`getMerchantDetailsRequest <http://developer.authorize.net/api/reference/index.html#transaction-reporting-get-merchant-details>`_
|
|
67
|
+
|
|
68
|
+
:raises AuthorizenetControllerExecutionError: If the API call fails.
|
|
69
|
+
:returns: A merchant details object, if found.
|
|
70
|
+
:rtype: :py:obj:`dict` | :py:obj:`None`
|
|
71
|
+
|
|
72
|
+
"""
|
|
73
|
+
request = apicontractsv1.getMerchantDetailsRequest(
|
|
74
|
+
merchantAuthentication=get_merchant_auth()
|
|
75
|
+
)
|
|
76
|
+
controller = apicontrollers.getMerchantDetailsController(request)
|
|
77
|
+
return AuthorizenetControllerExecutor.execute_controller(controller)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def get_transaction(id: int | str) -> dict | None:
|
|
81
|
+
"""
|
|
82
|
+
Returns Authorizenet transaction details by id.
|
|
83
|
+
|
|
84
|
+
`getTransactionDetailsRequest <https://developer.authorize.net/api/reference/index.html#transaction-reporting-get-transaction-details>`_
|
|
85
|
+
|
|
86
|
+
:param id: An Authorizenet transaction id.
|
|
87
|
+
:type id: :py:obj:`int` | :py:obj:`str`
|
|
88
|
+
:raises ValueError: If ``id`` was provided as a string containing non-digits.
|
|
89
|
+
:raises AuthorizenetControllerExecutionError: If the API call fails.
|
|
90
|
+
:returns: A transaction object, if found.
|
|
91
|
+
:rtype: :py:obj:`dict` | :py:obj:`None`
|
|
92
|
+
|
|
93
|
+
"""
|
|
94
|
+
if isinstance(id, str) and not id.isdigit():
|
|
95
|
+
raise ValueError(f"'id' can only contain digits, got '{id}'.")
|
|
96
|
+
|
|
97
|
+
request = apicontractsv1.getTransactionDetailsRequest(
|
|
98
|
+
merchantAuthentication=get_merchant_auth(), transId=str(id)
|
|
99
|
+
)
|
|
100
|
+
controller = apicontrollers.getTransactionDetailsController(request)
|
|
101
|
+
return AuthorizenetControllerExecutor.execute_controller(controller)
|
|
102
|
+
|
|
103
|
+
|
|
8
104
|
def get_customer_profile_ids() -> list[int]:
|
|
9
105
|
"""
|
|
10
106
|
Returns a list of all customer profile ids in Authorizenet.
|
|
11
107
|
|
|
12
|
-
:raises
|
|
108
|
+
:raises AuthorizenetControllerExecutionError: If the API call fails.
|
|
13
109
|
:returns: A list of all customer profile ids in Authorizenet.
|
|
14
110
|
:rtype: :py:obj:`list`
|
|
15
111
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import uuid
|
|
3
|
+
from contextlib import AsyncExitStack
|
|
4
|
+
|
|
5
|
+
from aiobotocore.session import AioSession
|
|
6
|
+
|
|
7
|
+
from terminusgps.django.validators import validate_e164_phone_number
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AWSNotifier:
|
|
11
|
+
def __init__(self, region: str = "us-east-1") -> None:
|
|
12
|
+
self._client = None
|
|
13
|
+
self._region = region
|
|
14
|
+
self._exit_stack = AsyncExitStack()
|
|
15
|
+
|
|
16
|
+
async def __aenter__(self):
|
|
17
|
+
session = AioSession()
|
|
18
|
+
self._client = await self._exit_stack.enter_async_context(
|
|
19
|
+
session.create_client("sns")
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
23
|
+
await self._exit_stack.__aexit__(exc_type, exc_val, exc_tb)
|
|
24
|
+
|
|
25
|
+
async def send_sms(
|
|
26
|
+
self, phone_number: str, message: str, message_id: str, group_id: str
|
|
27
|
+
) -> dict:
|
|
28
|
+
validate_e164_phone_number(phone_number)
|
|
29
|
+
await self._client.publish(
|
|
30
|
+
**{
|
|
31
|
+
"PhoneNumber": phone_number,
|
|
32
|
+
"Message": message,
|
|
33
|
+
"MessageDeduplicationId": message_id,
|
|
34
|
+
"MessageGroupId": group_id,
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
async def main() -> None:
|
|
40
|
+
notifier = AWSNotifier()
|
|
41
|
+
message_id = str(uuid.uuid4())
|
|
42
|
+
await notifier.send_sms(
|
|
43
|
+
"+17133049421", "This is a test message", message_id, "message-group"
|
|
44
|
+
)
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from django.core.exceptions import ValidationError
|
|
2
|
+
from django.utils.translation import gettext_lazy as _
|
|
3
|
+
|
|
4
|
+
VALID_COUNTRY_CODES = ("+1", "+52")
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def validate_e164_phone_number(value: str) -> None:
|
|
8
|
+
"""Raises :py:exec:`~django.core.exceptions.ValidationError` if the value is not a valid `E.164 <https://en.wikipedia.org/wiki/E.164>`_ formatted phone number."""
|
|
9
|
+
if not value.startswith("+"):
|
|
10
|
+
raise ValidationError(
|
|
11
|
+
_("E.164 phone number must begin with a '+', got '%(char)s'."),
|
|
12
|
+
code="invalid",
|
|
13
|
+
params={"char": value[0]},
|
|
14
|
+
)
|
|
15
|
+
if " " in value:
|
|
16
|
+
raise ValidationError(
|
|
17
|
+
_("E.164 phone number cannot contain spaces, got '%(value)s'."),
|
|
18
|
+
code="invalid",
|
|
19
|
+
params={"value": value},
|
|
20
|
+
)
|
|
21
|
+
if "-" in value:
|
|
22
|
+
raise ValidationError(
|
|
23
|
+
_("E.164 phone number cannot contain hyphens, got '%(value)s'."),
|
|
24
|
+
code="invalid",
|
|
25
|
+
params={"value": value},
|
|
26
|
+
)
|
|
27
|
+
if len(value) < 12:
|
|
28
|
+
raise ValidationError(
|
|
29
|
+
_(
|
|
30
|
+
"E.164 phone number cannot be less than 12 characters in length, got %(len)s."
|
|
31
|
+
),
|
|
32
|
+
code="invalid",
|
|
33
|
+
params={"len": len(value)},
|
|
34
|
+
)
|
|
35
|
+
if len(value) > 15:
|
|
36
|
+
raise ValidationError(
|
|
37
|
+
_(
|
|
38
|
+
"E.164 phone number cannot be greater than 15 characters in length, got %(len)s."
|
|
39
|
+
),
|
|
40
|
+
code="invalid",
|
|
41
|
+
params={"len": len(value)},
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
country_code: str = value[:-10]
|
|
45
|
+
area_code: str = value[-10:-7]
|
|
46
|
+
subscriber_number: str = value[-7:]
|
|
47
|
+
|
|
48
|
+
if len(country_code) < 2 or len(country_code) > 5:
|
|
49
|
+
raise ValidationError(
|
|
50
|
+
_(
|
|
51
|
+
"E.164 phone number country code must be between 2 and 5 characters in length, got %(len)s."
|
|
52
|
+
),
|
|
53
|
+
code="invalid",
|
|
54
|
+
params={"len": len(country_code)},
|
|
55
|
+
)
|
|
56
|
+
if country_code not in VALID_COUNTRY_CODES:
|
|
57
|
+
raise ValidationError(
|
|
58
|
+
_(
|
|
59
|
+
"E.164 phone number cannot contain an invalid country code, got '%(country_code)s'."
|
|
60
|
+
),
|
|
61
|
+
code="invalid",
|
|
62
|
+
params={"country_code": country_code},
|
|
63
|
+
)
|
|
64
|
+
if not len(area_code) == 3:
|
|
65
|
+
raise ValidationError(
|
|
66
|
+
_(
|
|
67
|
+
"E.164 phone number must contain a 3-digit area code, got '%(area_code)s'."
|
|
68
|
+
),
|
|
69
|
+
code="invalid",
|
|
70
|
+
params={"area_code": area_code},
|
|
71
|
+
)
|
|
72
|
+
if not area_code.isdigit():
|
|
73
|
+
raise ValidationError(
|
|
74
|
+
_("E.164 phone number must have a valid area code, got '%(area_code)s'"),
|
|
75
|
+
code="invalid",
|
|
76
|
+
params={"area_code": area_code},
|
|
77
|
+
)
|
|
78
|
+
if not len(subscriber_number) == 7:
|
|
79
|
+
raise ValidationError(
|
|
80
|
+
_(
|
|
81
|
+
"E.164 phone number must contain a 7-digit subscriber number, got '%(subscriber_number)s'."
|
|
82
|
+
),
|
|
83
|
+
code="invalid",
|
|
84
|
+
params={"subscriber_number": subscriber_number},
|
|
85
|
+
)
|
|
86
|
+
if not subscriber_number.isdigit():
|
|
87
|
+
raise ValidationError(
|
|
88
|
+
_(
|
|
89
|
+
"E.164 phone number must have a valid subscriber number, got '%(subscriber_number)s'"
|
|
90
|
+
),
|
|
91
|
+
code="invalid",
|
|
92
|
+
params={"subscriber_number": subscriber_number},
|
|
93
|
+
)
|
terminusgps/aws/connect.py
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
|
|
3
|
-
import jwt
|
|
4
|
-
from django.conf import settings
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def get_aws_connect_jwt(widget_id: str, expires_in: int = 500) -> str:
|
|
8
|
-
if expires_in > 600:
|
|
9
|
-
raise ValueError(f"'expires_in' must be less than 600, got '{expires_in}'.")
|
|
10
|
-
|
|
11
|
-
payload = {
|
|
12
|
-
"sub": widget_id,
|
|
13
|
-
"iat": datetime.datetime.utcnow(),
|
|
14
|
-
"exp": datetime.datetime.utcnow() - datetime.timedelta(seconds=expires_in),
|
|
15
|
-
"segmentAttributes": {"connect:Subtype": {"ValueString": "connect:Guide"}},
|
|
16
|
-
}
|
|
17
|
-
header = {"typ": "JWT", "alg": "HS256"}
|
|
18
|
-
encoded_token = jwt.encode(
|
|
19
|
-
payload, settings.CONNECT_SECRET, algorithm=header["alg"], headers=header
|
|
20
|
-
)
|
|
21
|
-
return encoded_token
|
|
File without changes
|
{python_terminusgps-33.2.0.dist-info → python_terminusgps-33.3.1.dist-info}/licenses/COPYING
RENAMED
|
File without changes
|