simplepush 3.5.0__tar.gz → 3.6.1__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.
- {simplepush-3.5.0 → simplepush-3.6.1}/PKG-INFO +1 -1
- {simplepush-3.5.0 → simplepush-3.6.1}/pyproject.toml +1 -1
- {simplepush-3.5.0 → simplepush-3.6.1}/src/simplepush/api.py +15 -2
- {simplepush-3.5.0 → simplepush-3.6.1}/src/simplepush/client.py +2 -2
- {simplepush-3.5.0 → simplepush-3.6.1}/.gitignore +0 -0
- {simplepush-3.5.0 → simplepush-3.6.1}/LICENSE +0 -0
- {simplepush-3.5.0 → simplepush-3.6.1}/README.md +0 -0
- {simplepush-3.5.0 → simplepush-3.6.1}/src/simplepush/__init__.py +0 -0
- {simplepush-3.5.0 → simplepush-3.6.1}/src/simplepush/_extras.py +0 -0
- {simplepush-3.5.0 → simplepush-3.6.1}/src/simplepush/crypto.py +0 -0
- {simplepush-3.5.0 → simplepush-3.6.1}/src/simplepush/decrypt.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: simplepush
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.6.1
|
|
4
4
|
Summary: Python client for Simplepush (tasks, notifications, events, end-to-end encryption).
|
|
5
5
|
Project-URL: Homepage, https://simplepu.sh
|
|
6
6
|
Project-URL: Documentation, https://simplepu.sh/guide/python-sdk
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "simplepush"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.6.1"
|
|
8
8
|
description = "Python client for Simplepush (tasks, notifications, events, end-to-end encryption)."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -683,6 +683,7 @@ class _BaseClient:
|
|
|
683
683
|
input: NotificationInput | None = None,
|
|
684
684
|
image: "str | os.PathLike | None" = None,
|
|
685
685
|
audio: "str | os.PathLike | None" = None,
|
|
686
|
+
link: str | None = None,
|
|
686
687
|
password: str | None = None,
|
|
687
688
|
tag: str | None = None,
|
|
688
689
|
critical: bool = False,
|
|
@@ -725,6 +726,10 @@ class _BaseClient:
|
|
|
725
726
|
audio: Optional single audio clip (URL or local path), like `image`.
|
|
726
727
|
Plays inline on iOS; Android has no inline audio. Mutually
|
|
727
728
|
exclusive with `image` (a notification shows at most one media).
|
|
729
|
+
link: Optional URL shown as an "Open link" button on the push. Any
|
|
730
|
+
scheme: an https URL opens the browser, an app's deep link
|
|
731
|
+
(`unifi-protect://...`) opens that app. Mutually exclusive
|
|
732
|
+
with `input` (the input's buttons take the action slots).
|
|
728
733
|
password: Optional password to encrypt body fields with. Requires a
|
|
729
734
|
topic (used as the salt for key derivation). Falls back to
|
|
730
735
|
the client's default `password` when omitted. Not accepted
|
|
@@ -750,7 +755,7 @@ class _BaseClient:
|
|
|
750
755
|
return self._create_notification(
|
|
751
756
|
topic=topic, member=member, broadcast=broadcast,
|
|
752
757
|
title=title, content=content, input=input,
|
|
753
|
-
image=image, audio=audio,
|
|
758
|
+
image=image, audio=audio, link=link,
|
|
754
759
|
password=password if password is not None else self._send_password(topic),
|
|
755
760
|
tag=tag, critical=critical, shared=shared,
|
|
756
761
|
)
|
|
@@ -966,7 +971,7 @@ class _BaseClient:
|
|
|
966
971
|
|
|
967
972
|
def _create_notification(self, *, topic=None, member=None, broadcast=False,
|
|
968
973
|
title=None, content=None, input=None, image=None, audio=None,
|
|
969
|
-
password=None, tag=None, critical=False,
|
|
974
|
+
link=None, password=None, tag=None, critical=False,
|
|
970
975
|
shared=False) -> "Notification | NotificationGroup":
|
|
971
976
|
if not content and input is None:
|
|
972
977
|
raise ValueError("Either content or an input must be provided")
|
|
@@ -990,6 +995,8 @@ class _BaseClient:
|
|
|
990
995
|
_validate_actions(input.actions)
|
|
991
996
|
if image is not None and audio is not None:
|
|
992
997
|
raise ValueError("a notification can carry at most one media attachment (image or audio, not both)")
|
|
998
|
+
if link is not None and input is not None:
|
|
999
|
+
raise ValueError("a notification carries either an input or a link, not both: the input's buttons take the action slots, so the link would never be shown")
|
|
993
1000
|
|
|
994
1001
|
# A notification carries at most one input, sent as `textInput {}` XOR
|
|
995
1002
|
# `choiceInput {options}` XOR `actionInput {actions}`. For actions, both
|
|
@@ -1029,6 +1036,8 @@ class _BaseClient:
|
|
|
1029
1036
|
tag = encrypt(tag, dk.symmetric_key)
|
|
1030
1037
|
if choice_options is not None:
|
|
1031
1038
|
choice_options = [encrypt(opt, dk.symmetric_key) for opt in choice_options]
|
|
1039
|
+
if link is not None:
|
|
1040
|
+
link = encrypt(link, dk.symmetric_key)
|
|
1032
1041
|
if action_defs is not None:
|
|
1033
1042
|
# Key AND label, exactly like a task's ActionsInput: the key
|
|
1034
1043
|
# usually carries the same meaning as the label ("approve"), so
|
|
@@ -1053,6 +1062,8 @@ class _BaseClient:
|
|
|
1053
1062
|
tag = encrypt(tag, key)
|
|
1054
1063
|
if choice_options is not None:
|
|
1055
1064
|
choice_options = [encrypt(opt, key) for opt in choice_options]
|
|
1065
|
+
if link is not None:
|
|
1066
|
+
link = encrypt(link, key)
|
|
1056
1067
|
if action_defs is not None:
|
|
1057
1068
|
for a in action_defs: # key AND label, as above
|
|
1058
1069
|
a["key"] = encrypt(a["key"], key)
|
|
@@ -1069,6 +1080,8 @@ class _BaseClient:
|
|
|
1069
1080
|
}
|
|
1070
1081
|
if media_dict is not None:
|
|
1071
1082
|
payload["media"] = media_dict
|
|
1083
|
+
if link is not None:
|
|
1084
|
+
payload["link"] = link
|
|
1072
1085
|
if topic is not None:
|
|
1073
1086
|
payload["topic"] = topic
|
|
1074
1087
|
if member is not None:
|
|
@@ -1471,7 +1471,7 @@ class Task:
|
|
|
1471
1471
|
def append(self, *, title: str | None = None, content: str | None = None,
|
|
1472
1472
|
inputs=None, links: list[str] | None = None,
|
|
1473
1473
|
files: "list[str | os.PathLike] | None" = None,
|
|
1474
|
-
auto_commit: bool =
|
|
1474
|
+
auto_commit: bool = False, critical: bool = False,
|
|
1475
1475
|
reply: "ReplyMode | Literal['one-shot', 'sticky', 'one-time-per-user'] | None" = None,
|
|
1476
1476
|
content_format: "ContentFormat | Literal['plain', 'markdown'] | None" = None) -> "Subtask":
|
|
1477
1477
|
"""Append a subtask to this task's chain and return a `Subtask` handle.
|
|
@@ -1643,7 +1643,7 @@ class TaskGroup:
|
|
|
1643
1643
|
inputs=None, links: "list[str] | None" = None,
|
|
1644
1644
|
files: "list[str | os.PathLike] | None" = None,
|
|
1645
1645
|
instances: "list[str | Task] | None" = None,
|
|
1646
|
-
auto_commit: bool =
|
|
1646
|
+
auto_commit: bool = False, critical: bool = False,
|
|
1647
1647
|
reply: "ReplyMode | Literal['one-shot', 'sticky', 'one-time-per-user'] | None" = None,
|
|
1648
1648
|
content_format: "ContentFormat | Literal['plain', 'markdown'] | None" = None) -> "list[Subtask]":
|
|
1649
1649
|
"""Append a subtask to every member instance's chain atomically — or
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|