python-ntfy 0.8.0__tar.gz → 0.9.0__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.
- {python_ntfy-0.8.0 → python_ntfy-0.9.0}/PKG-INFO +2 -2
- {python_ntfy-0.8.0 → python_ntfy-0.9.0}/README.md +1 -1
- {python_ntfy-0.8.0 → python_ntfy-0.9.0}/pyproject.toml +24 -1
- python_ntfy-0.9.0/python_ntfy/__init__.py +17 -0
- python_ntfy-0.9.0/python_ntfy/_ntfy.py +19 -0
- python_ntfy-0.9.0/python_ntfy/client.py +146 -0
- python_ntfy-0.9.0/python_ntfy/py.typed +0 -0
- python_ntfy-0.8.0/python_ntfy/__init__.py +0 -3
- python_ntfy-0.8.0/python_ntfy/_ntfy.py +0 -134
- {python_ntfy-0.8.0 → python_ntfy-0.9.0}/python_ntfy/_exceptions.py +0 -0
- {python_ntfy-0.8.0 → python_ntfy-0.9.0}/python_ntfy/_get_functions.py +0 -0
- {python_ntfy-0.8.0 → python_ntfy-0.9.0}/python_ntfy/_send_functions.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-ntfy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: An ntfy library aiming for feature completeness
|
|
5
5
|
Keywords: ntfy,notifications,push,http,api
|
|
6
6
|
Author: Matthew Cane
|
|
@@ -43,7 +43,7 @@ Description-Content-Type: text/markdown
|
|
|
43
43
|
# A Python Library For ntfy
|
|
44
44
|
|
|
45
45
|

|
|
46
|
-
](https://pepy.tech/projects/python-ntfy)
|
|
47
47
|

|
|
48
48
|
|
|
49
49
|
An easy-to-use python library for the [ntfy notification service](https://ntfy.sh/). Aiming for full feature support and a super easy to use interface.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# A Python Library For ntfy
|
|
2
2
|
|
|
3
3
|

|
|
4
|
-
](https://pepy.tech/projects/python-ntfy)
|
|
5
5
|

|
|
6
6
|
|
|
7
7
|
An easy-to-use python library for the [ntfy notification service](https://ntfy.sh/). Aiming for full feature support and a super easy to use interface.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-ntfy"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.9.0"
|
|
4
4
|
description = "An ntfy library aiming for feature completeness"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -74,6 +74,9 @@ dev = [
|
|
|
74
74
|
[tool.ruff]
|
|
75
75
|
target-version = "py312"
|
|
76
76
|
|
|
77
|
+
[tool.ruff.lint.isort]
|
|
78
|
+
combine-as-imports = true
|
|
79
|
+
|
|
77
80
|
[tool.ruff.lint]
|
|
78
81
|
select = [
|
|
79
82
|
"E", # PycodeStyle errors
|
|
@@ -125,3 +128,23 @@ addopts = [
|
|
|
125
128
|
"--cov-fail-under=95",
|
|
126
129
|
"--cov-report=term-missing",
|
|
127
130
|
]
|
|
131
|
+
|
|
132
|
+
[tool.mypy]
|
|
133
|
+
python_version = "3.12"
|
|
134
|
+
warn_unused_ignores = true
|
|
135
|
+
warn_redundant_casts = true
|
|
136
|
+
warn_unreachable = true
|
|
137
|
+
no_implicit_optional = true
|
|
138
|
+
strict_equality = true
|
|
139
|
+
pretty = true
|
|
140
|
+
# Default expectations for the codebase; public modules may override to be stricter.
|
|
141
|
+
disallow_incomplete_defs = false
|
|
142
|
+
disallow_untyped_defs = false
|
|
143
|
+
|
|
144
|
+
[[tool.mypy.overrides]]
|
|
145
|
+
module = [
|
|
146
|
+
"python_ntfy.client",
|
|
147
|
+
"python_ntfy.__init__",
|
|
148
|
+
]
|
|
149
|
+
disallow_incomplete_defs = true
|
|
150
|
+
disallow_untyped_defs = true
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from ._exceptions import MessageSendError as MessageSendError
|
|
2
|
+
from ._send_functions import (
|
|
3
|
+
BroadcastAction as BroadcastAction,
|
|
4
|
+
HttpAction as HttpAction,
|
|
5
|
+
MessagePriority as MessagePriority,
|
|
6
|
+
ViewAction as ViewAction,
|
|
7
|
+
)
|
|
8
|
+
from .client import NtfyClient as NtfyClient
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"BroadcastAction",
|
|
12
|
+
"HttpAction",
|
|
13
|
+
"MessagePriority",
|
|
14
|
+
"MessageSendError",
|
|
15
|
+
"NtfyClient",
|
|
16
|
+
"ViewAction",
|
|
17
|
+
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Compatibility shim for historical import path.
|
|
2
|
+
|
|
3
|
+
Prefer importing from `python_ntfy` package root:
|
|
4
|
+
|
|
5
|
+
from python_ntfy import NtfyClient
|
|
6
|
+
|
|
7
|
+
This module re-exports `NtfyClient` to maintain backward compatibility with
|
|
8
|
+
older references like `python_ntfy._ntfy.NtfyClient`.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from warnings import warn
|
|
12
|
+
|
|
13
|
+
from .client import NtfyClient as NtfyClient
|
|
14
|
+
|
|
15
|
+
warn(
|
|
16
|
+
"`python_ntfy._ntfy` is deprecated and will be removed in a future version. Please import from `python_ntfy` instead.",
|
|
17
|
+
DeprecationWarning,
|
|
18
|
+
stacklevel=2,
|
|
19
|
+
)
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from ._get_functions import get_cached_messages as _get_cached_messages
|
|
8
|
+
from ._send_functions import (
|
|
9
|
+
BroadcastAction as _BroadcastAction,
|
|
10
|
+
HttpAction as _HttpAction,
|
|
11
|
+
MessagePriority as _MessagePriority,
|
|
12
|
+
ViewAction as _ViewAction,
|
|
13
|
+
send as _send_message,
|
|
14
|
+
send_file as _send_file,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NtfyClient:
|
|
19
|
+
"""A client for interacting with the ntfy notification service."""
|
|
20
|
+
|
|
21
|
+
# Backwards-compatible attribute exposure (discouraged for new code):
|
|
22
|
+
BroadcastAction = _BroadcastAction
|
|
23
|
+
HttpAction = _HttpAction
|
|
24
|
+
MessagePriority = _MessagePriority
|
|
25
|
+
ViewAction = _ViewAction
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
topic: str,
|
|
30
|
+
server: str = "https://ntfy.sh",
|
|
31
|
+
auth: tuple[str, str] | str | None = None,
|
|
32
|
+
) -> None:
|
|
33
|
+
"""Initialize the client.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
topic: The topic to use for this client.
|
|
37
|
+
server: The server base URL (must include protocol, e.g., https://).
|
|
38
|
+
auth: Credentials for this client. Takes precedence over environment
|
|
39
|
+
variables. May be a tuple ``(user, password)`` for Basic auth
|
|
40
|
+
or a token string for Bearer auth.
|
|
41
|
+
"""
|
|
42
|
+
self._server = os.environ.get("NTFY_SERVER") or server
|
|
43
|
+
self._topic = topic
|
|
44
|
+
self.__set_url(self._server, topic)
|
|
45
|
+
self._auth: tuple[str, str] | None = self._resolve_auth(auth)
|
|
46
|
+
|
|
47
|
+
def _resolve_auth(
|
|
48
|
+
self, auth: tuple[str, str] | str | None
|
|
49
|
+
) -> tuple[str, str] | None:
|
|
50
|
+
"""Resolve authentication credentials using args or environment variables."""
|
|
51
|
+
# Explicitly provided credentials take precedence (including empty string)
|
|
52
|
+
if auth is not None:
|
|
53
|
+
if isinstance(auth, tuple):
|
|
54
|
+
return auth
|
|
55
|
+
if isinstance(auth, str):
|
|
56
|
+
return ("", auth)
|
|
57
|
+
|
|
58
|
+
# Fallback to environment variables
|
|
59
|
+
user = os.environ.get("NTFY_USER")
|
|
60
|
+
password = os.environ.get("NTFY_PASSWORD")
|
|
61
|
+
token = os.environ.get("NTFY_TOKEN")
|
|
62
|
+
|
|
63
|
+
if user and password:
|
|
64
|
+
return (user, password)
|
|
65
|
+
if token:
|
|
66
|
+
return ("", token)
|
|
67
|
+
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
def __set_url(self, server: str, topic: str) -> None:
|
|
71
|
+
self.url = server.strip("/") + "/" + topic
|
|
72
|
+
|
|
73
|
+
def set_topic(self, topic: str) -> None:
|
|
74
|
+
"""Set a new topic for this client."""
|
|
75
|
+
self._topic = topic
|
|
76
|
+
self.__set_url(self._server, self._topic)
|
|
77
|
+
|
|
78
|
+
def get_topic(self) -> str:
|
|
79
|
+
"""Get the current topic."""
|
|
80
|
+
return self._topic
|
|
81
|
+
|
|
82
|
+
# Public API methods delegate to internal helpers for implementation
|
|
83
|
+
|
|
84
|
+
def send(
|
|
85
|
+
self,
|
|
86
|
+
message: str,
|
|
87
|
+
title: str | None = None,
|
|
88
|
+
priority: _MessagePriority = _MessagePriority.DEFAULT,
|
|
89
|
+
tags: list[str] | None = None,
|
|
90
|
+
actions: list[_ViewAction | _BroadcastAction | _HttpAction] | None = None,
|
|
91
|
+
schedule: datetime | None = None,
|
|
92
|
+
format_as_markdown: bool = False,
|
|
93
|
+
timeout_seconds: int = 5,
|
|
94
|
+
email: str | None = None,
|
|
95
|
+
) -> dict:
|
|
96
|
+
"""Send a text-based message to the server."""
|
|
97
|
+
return _send_message(
|
|
98
|
+
self,
|
|
99
|
+
message=message,
|
|
100
|
+
title=title,
|
|
101
|
+
priority=priority,
|
|
102
|
+
tags=tags,
|
|
103
|
+
actions=actions,
|
|
104
|
+
schedule=schedule,
|
|
105
|
+
format_as_markdown=format_as_markdown,
|
|
106
|
+
timeout_seconds=timeout_seconds,
|
|
107
|
+
email=email,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def send_file(
|
|
111
|
+
self,
|
|
112
|
+
file: str | Path,
|
|
113
|
+
title: str | None = None,
|
|
114
|
+
priority: _MessagePriority = _MessagePriority.DEFAULT,
|
|
115
|
+
tags: list[str] | None = None,
|
|
116
|
+
actions: list[_ViewAction | _BroadcastAction | _HttpAction] | None = None,
|
|
117
|
+
schedule: datetime | None = None,
|
|
118
|
+
timeout_seconds: int = 30,
|
|
119
|
+
email: str | None = None,
|
|
120
|
+
) -> dict:
|
|
121
|
+
"""Send a file to the server."""
|
|
122
|
+
return _send_file(
|
|
123
|
+
self,
|
|
124
|
+
file=file,
|
|
125
|
+
title=title,
|
|
126
|
+
priority=priority,
|
|
127
|
+
tags=tags,
|
|
128
|
+
actions=actions,
|
|
129
|
+
schedule=schedule,
|
|
130
|
+
timeout_seconds=timeout_seconds,
|
|
131
|
+
email=email,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
def get_cached_messages(
|
|
135
|
+
self,
|
|
136
|
+
since: str = "all",
|
|
137
|
+
scheduled: bool = False,
|
|
138
|
+
timeout_seconds: int = 10,
|
|
139
|
+
) -> list[dict]:
|
|
140
|
+
"""Get cached messages from the server."""
|
|
141
|
+
return _get_cached_messages(
|
|
142
|
+
self,
|
|
143
|
+
since=since,
|
|
144
|
+
scheduled=scheduled,
|
|
145
|
+
timeout_seconds=timeout_seconds,
|
|
146
|
+
)
|
|
File without changes
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
"""This module provides the NtfyClient class for interacting with the ntfy notification service.
|
|
2
|
-
|
|
3
|
-
The NtfyClient class allows users to send notifications, files, and perform various actions
|
|
4
|
-
through the ntfy.sh service. It also supports retrieving cached messages.
|
|
5
|
-
|
|
6
|
-
Typical usage example:
|
|
7
|
-
|
|
8
|
-
client = NtfyClient(topic="my_topic")
|
|
9
|
-
client.send("Hello, World!")
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
import os
|
|
13
|
-
|
|
14
|
-
from ._get_functions import get_cached_messages
|
|
15
|
-
from ._send_functions import (
|
|
16
|
-
BroadcastAction,
|
|
17
|
-
HttpAction,
|
|
18
|
-
MessagePriority,
|
|
19
|
-
ViewAction,
|
|
20
|
-
send,
|
|
21
|
-
send_file,
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class GetFunctionsMixin:
|
|
26
|
-
"""Mixin for getting messages."""
|
|
27
|
-
|
|
28
|
-
get_cached_messages = get_cached_messages
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class SendFunctionsMixin:
|
|
32
|
-
"""Mixin for sending messages."""
|
|
33
|
-
|
|
34
|
-
send = send
|
|
35
|
-
send_file = send_file
|
|
36
|
-
BroadcastAction = BroadcastAction
|
|
37
|
-
HttpAction = HttpAction
|
|
38
|
-
MessagePriority = MessagePriority
|
|
39
|
-
ViewAction = ViewAction
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class NtfyClient(GetFunctionsMixin, SendFunctionsMixin):
|
|
43
|
-
"""A class for interacting with the ntfy notification service."""
|
|
44
|
-
|
|
45
|
-
def __init__(
|
|
46
|
-
self,
|
|
47
|
-
topic: str,
|
|
48
|
-
server: str = "https://ntfy.sh",
|
|
49
|
-
auth: tuple[str, str] | str | None = None,
|
|
50
|
-
) -> None:
|
|
51
|
-
"""Itinialize the NtfyClient.
|
|
52
|
-
|
|
53
|
-
Args:
|
|
54
|
-
topic: The topic to use for this client
|
|
55
|
-
server: The server to connect to. Must include the protocol (http/https)
|
|
56
|
-
auth: The authentication credentials to use for this client. Takes precedence over environment variables. Can be a tuple of (user, password) or a token.
|
|
57
|
-
|
|
58
|
-
Returns:
|
|
59
|
-
None
|
|
60
|
-
|
|
61
|
-
Exceptions:
|
|
62
|
-
None
|
|
63
|
-
|
|
64
|
-
Examples:
|
|
65
|
-
client = NtfyClient(topic="my_topic")
|
|
66
|
-
"""
|
|
67
|
-
self._server = os.environ.get("NTFY_SERVER") or server
|
|
68
|
-
self._topic = topic
|
|
69
|
-
self.__set_url(self._server, topic)
|
|
70
|
-
self._auth: tuple[str, str] | None = self._resolve_auth(auth)
|
|
71
|
-
|
|
72
|
-
def _resolve_auth(
|
|
73
|
-
self, auth: tuple[str, str] | str | None
|
|
74
|
-
) -> tuple[str, str] | None:
|
|
75
|
-
"""Resolve the authentication credentials.
|
|
76
|
-
|
|
77
|
-
Args:
|
|
78
|
-
auth: The authentication credentials to use for this client. Takes precedence over environment variables. Can be a tuple of (user, password) or a token string.
|
|
79
|
-
|
|
80
|
-
Returns:
|
|
81
|
-
tuple[str, str] | None: The authentication credentials.
|
|
82
|
-
"""
|
|
83
|
-
# If the user has supplied credentials, use them (including empty string)
|
|
84
|
-
if auth is not None:
|
|
85
|
-
if isinstance(auth, tuple):
|
|
86
|
-
return auth
|
|
87
|
-
if isinstance(auth, str):
|
|
88
|
-
return ("", auth)
|
|
89
|
-
|
|
90
|
-
# Otherwise, check environment variables
|
|
91
|
-
user = os.environ.get("NTFY_USER")
|
|
92
|
-
password = os.environ.get("NTFY_PASSWORD")
|
|
93
|
-
token = os.environ.get("NTFY_TOKEN")
|
|
94
|
-
|
|
95
|
-
if user and password:
|
|
96
|
-
return (user, password)
|
|
97
|
-
|
|
98
|
-
if token:
|
|
99
|
-
return ("", token)
|
|
100
|
-
|
|
101
|
-
# If no credentials are found, return None
|
|
102
|
-
return None
|
|
103
|
-
|
|
104
|
-
def __set_url(
|
|
105
|
-
self,
|
|
106
|
-
server,
|
|
107
|
-
topic,
|
|
108
|
-
) -> None:
|
|
109
|
-
self.url = server.strip("/") + "/" + topic
|
|
110
|
-
|
|
111
|
-
def set_topic(
|
|
112
|
-
self,
|
|
113
|
-
topic: str,
|
|
114
|
-
) -> None:
|
|
115
|
-
"""Set a new topic for the client.
|
|
116
|
-
|
|
117
|
-
Args:
|
|
118
|
-
topic: The topic to set for this client.
|
|
119
|
-
|
|
120
|
-
Returns:
|
|
121
|
-
None
|
|
122
|
-
"""
|
|
123
|
-
self._topic = topic
|
|
124
|
-
self.__set_url(self._server, self._topic)
|
|
125
|
-
|
|
126
|
-
def get_topic(
|
|
127
|
-
self,
|
|
128
|
-
) -> str:
|
|
129
|
-
"""Get the current topic.
|
|
130
|
-
|
|
131
|
-
Returns:
|
|
132
|
-
str: The current topic.
|
|
133
|
-
"""
|
|
134
|
-
return self._topic
|
|
File without changes
|
|
File without changes
|
|
File without changes
|