python-ntfy 0.1.0__tar.gz → 0.2.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.
@@ -0,0 +1,88 @@
1
+ Metadata-Version: 2.1
2
+ Name: python-ntfy
3
+ Version: 0.2.1
4
+ Summary: An ntfy library aiming for feature completeness
5
+ Author: Matthew Cane
6
+ Author-email: matthew.cane0@gmail.com
7
+ Requires-Python: >=3.11,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Requires-Dist: requests (>=2.31.0,<3.0.0)
13
+ Description-Content-Type: text/markdown
14
+
15
+ # A Python Library For ntfy.sh
16
+
17
+ An easy-to-use ntfy python library. Aiming for full feature support.
18
+
19
+ ## Quickstart
20
+
21
+ 1. Install using pip with `pip3 install python-ntfy`
22
+ 2. Configure the following environment variables:
23
+ - `NTFY_USER`: The username for your server (if required)
24
+ - `NTFY_PASSWORD`: The password for your server (if required)
25
+ - `NTFY_SERVER`: The server URL (defaults to https://ntft.sh)
26
+ 3. Setup your application to use the library:
27
+
28
+ ```python
29
+ # Import the ntfy client
30
+ from python_ntfy import NtfyClient
31
+
32
+ # Create an `NtfyClient` instance with a topic
33
+ client = NtfyClient(topic="Your topic")
34
+
35
+ # Send a message
36
+ client.send("Your message here")
37
+ ```
38
+
39
+ ## Supported Features
40
+
41
+ - Username + password auth
42
+ - Custom servers
43
+ - Sending plaintext messages
44
+ - Sending Markdown formatted text messages
45
+ - Retrieving cached messages
46
+ - Scheduled delivery
47
+
48
+ ## Future Features
49
+
50
+ - Access token auth
51
+ - Email notifications
52
+ - Tags
53
+ - Action buttons
54
+ - Send to multiple topics at once
55
+
56
+ ## Test and Development
57
+
58
+ This project uses:
59
+
60
+ - Poetry as it's dependency manager
61
+ - Ruff for linting and code formatting
62
+
63
+ To install dev dependencies, run `poetry install --with dev`.
64
+
65
+ ### Linting and Formatting
66
+
67
+ These can be run with:
68
+
69
+ - `poetry run ruff format`
70
+ - `poetry run ruff check`
71
+
72
+ ### Tests
73
+
74
+ This project is aiming for 95% code coverage. Any added features must include comprihensive tests.
75
+
76
+ You can run the tests against a local instance of `ntfy` *or* `ntfy.sh`.
77
+
78
+ #### Setup Steps
79
+
80
+ 1. To test against a *local* `ntfy` instance:
81
+ i. Create a container using `docker run -p 80:80 -it binwiederhier/ntfy serve --attachment-cache-dir=/cache --base-url=http://localhost`
82
+ ii. Set the following key in the `.env` file: `NTFY_SERVER=http://localhost`
83
+ iii. Add a dummy username and password to `.env` (see example.env)
84
+ 2. To test against https://ntfy.sh:
85
+ i. Add username and password for ntfy.sh to `.env` (see example.env)
86
+ 3. Run the tests with `poetry run pytest --cov`
87
+
88
+ The tests will sent messages to the `python_ntfy_testing` topic so you will need to subcribe to that topic to see the test messages.
@@ -0,0 +1,74 @@
1
+ # A Python Library For ntfy.sh
2
+
3
+ An easy-to-use ntfy python library. Aiming for full feature support.
4
+
5
+ ## Quickstart
6
+
7
+ 1. Install using pip with `pip3 install python-ntfy`
8
+ 2. Configure the following environment variables:
9
+ - `NTFY_USER`: The username for your server (if required)
10
+ - `NTFY_PASSWORD`: The password for your server (if required)
11
+ - `NTFY_SERVER`: The server URL (defaults to https://ntft.sh)
12
+ 3. Setup your application to use the library:
13
+
14
+ ```python
15
+ # Import the ntfy client
16
+ from python_ntfy import NtfyClient
17
+
18
+ # Create an `NtfyClient` instance with a topic
19
+ client = NtfyClient(topic="Your topic")
20
+
21
+ # Send a message
22
+ client.send("Your message here")
23
+ ```
24
+
25
+ ## Supported Features
26
+
27
+ - Username + password auth
28
+ - Custom servers
29
+ - Sending plaintext messages
30
+ - Sending Markdown formatted text messages
31
+ - Retrieving cached messages
32
+ - Scheduled delivery
33
+
34
+ ## Future Features
35
+
36
+ - Access token auth
37
+ - Email notifications
38
+ - Tags
39
+ - Action buttons
40
+ - Send to multiple topics at once
41
+
42
+ ## Test and Development
43
+
44
+ This project uses:
45
+
46
+ - Poetry as it's dependency manager
47
+ - Ruff for linting and code formatting
48
+
49
+ To install dev dependencies, run `poetry install --with dev`.
50
+
51
+ ### Linting and Formatting
52
+
53
+ These can be run with:
54
+
55
+ - `poetry run ruff format`
56
+ - `poetry run ruff check`
57
+
58
+ ### Tests
59
+
60
+ This project is aiming for 95% code coverage. Any added features must include comprihensive tests.
61
+
62
+ You can run the tests against a local instance of `ntfy` *or* `ntfy.sh`.
63
+
64
+ #### Setup Steps
65
+
66
+ 1. To test against a *local* `ntfy` instance:
67
+ i. Create a container using `docker run -p 80:80 -it binwiederhier/ntfy serve --attachment-cache-dir=/cache --base-url=http://localhost`
68
+ ii. Set the following key in the `.env` file: `NTFY_SERVER=http://localhost`
69
+ iii. Add a dummy username and password to `.env` (see example.env)
70
+ 2. To test against https://ntfy.sh:
71
+ i. Add username and password for ntfy.sh to `.env` (see example.env)
72
+ 3. Run the tests with `poetry run pytest --cov`
73
+
74
+ The tests will sent messages to the `python_ntfy_testing` topic so you will need to subcribe to that topic to see the test messages.
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-ntfy"
3
- version = "0.1.0"
3
+ version = "0.2.1"
4
4
  description = "An ntfy library aiming for feature completeness"
5
5
  authors = ["Matthew Cane <matthew.cane0@gmail.com>"]
6
6
  readme = "README.md"
@@ -9,11 +9,12 @@ readme = "README.md"
9
9
  python = "^3.11"
10
10
  requests = "^2.31.0"
11
11
 
12
- [tool.poetry.group.test.dependencies]
12
+ [tool.poetry.group.dev.dependencies]
13
13
  pytest = "^7.4.1"
14
14
  python-dotenv = "^1.0.0"
15
15
  pytest-asyncio = "^0.21.1"
16
16
  pytest-codecov = "^0.5.1"
17
+ ruff = "^0.7.0"
17
18
 
18
19
  [build-system]
19
20
  requires = ["poetry-core"]
@@ -2,7 +2,14 @@ import os
2
2
 
3
3
 
4
4
  class NtfyClient:
5
- from ._send_functions import send, send_file
5
+ from ._send_functions import (
6
+ send,
7
+ send_file,
8
+ MessagePriority,
9
+ ViewAction,
10
+ BroadcastAction,
11
+ HttpAction,
12
+ )
6
13
  from ._get_functions import get_cached_messages
7
14
 
8
15
  def __init__(
@@ -15,9 +22,9 @@ class NtfyClient:
15
22
  :param server: The server to connect to. Must include the protocol (http/https)
16
23
  :return:
17
24
  """
18
- self._server = server
25
+ self._server = os.environ.get("NTFY_SERVER") or server
19
26
  self._topic = topic
20
- self.__set_url(server, topic)
27
+ self.__set_url(self._server, topic)
21
28
 
22
29
  if (user := os.environ.get("NTFY_USER")) and (
23
30
  password := os.environ.get("NTFY_PASSWORD")
@@ -1,4 +1,5 @@
1
- import json, requests
1
+ import json
2
+ import requests
2
3
 
3
4
 
4
5
  def get_cached_messages(self, since: str = "all", scheduled: bool = False):
@@ -0,0 +1,202 @@
1
+ import json
2
+ import requests
3
+ from enum import Enum
4
+ from typing import Optional, Union
5
+
6
+
7
+ class MessagePriority(Enum):
8
+ """
9
+ Ntfy message priority levels.
10
+ """
11
+
12
+ MIN = "1"
13
+ LOW = "2"
14
+ DEFAULT = "3"
15
+ HIGH = "4"
16
+ MAX = "5"
17
+ URGENT = MAX
18
+
19
+
20
+ class ActionType(Enum):
21
+ """
22
+ Action button types
23
+ """
24
+
25
+ VIEW = "view"
26
+ BROADCAST = "broadcast"
27
+ HTTP = "http"
28
+
29
+
30
+ class Action:
31
+ def __init__(self, label: str, url: str, clear: bool = False):
32
+ self.label = label
33
+ self.url = url
34
+ self.actions: list = []
35
+ self.clear = clear
36
+
37
+
38
+ class ViewAction(Action):
39
+ def __init__(self, label: str, url: str, clear: bool = False):
40
+ self.action = ActionType.VIEW
41
+ super().__init__(label=label, url=url, clear=clear)
42
+
43
+ def to_dict(self):
44
+ return {
45
+ "action": self.action.value,
46
+ "label": self.label,
47
+ "url": self.url,
48
+ "clear": self.clear,
49
+ }
50
+
51
+ def to_header(self):
52
+ return f"action={self.action.value}, label={self.label}, url={self.url}, clear={self.clear}"
53
+
54
+
55
+ class BroadcastAction(Action):
56
+ def __init__(
57
+ self,
58
+ label: str,
59
+ intent: str = "io.heckel.ntfy.USER_ACTION",
60
+ extras: Optional[dict] = None,
61
+ clear: bool = False,
62
+ ):
63
+ self.action = ActionType.BROADCAST
64
+ self.intent = intent
65
+ self.extras = extras
66
+ super().__init__(label, ActionType.BROADCAST, clear)
67
+
68
+ def to_dict(self):
69
+ return {
70
+ "action": self.action.value,
71
+ "label": self.label,
72
+ "extras": self.extras,
73
+ "clear": self.clear,
74
+ }
75
+
76
+ def to_header(self):
77
+ extras = ""
78
+ if self.extras is not None:
79
+ for key, value in self.extras.items():
80
+ extras += f"{key}={value},"
81
+ return f"action={self.action.value}, label={self.label}, url={self.url}, clear={self.clear}"
82
+
83
+
84
+ class HttpAction(Action):
85
+ def __init__(
86
+ self,
87
+ label: str,
88
+ url: str,
89
+ method: str = "POST",
90
+ headers: Optional[dict] = None,
91
+ body: Optional[str] = None,
92
+ clear: bool = False,
93
+ ):
94
+ self.action = ActionType.HTTP
95
+ self.method = method
96
+ self.headers = headers
97
+ self.body = body
98
+ super().__init__(label, url, clear)
99
+
100
+ def to_dict(self):
101
+ action_dict = {
102
+ "action": self.action.value,
103
+ "label": self.label,
104
+ "url": self.url,
105
+ "method": self.method,
106
+ "clear": self.clear,
107
+ }
108
+ if self.headers:
109
+ action_dict["headers"] = self.headers
110
+ if self.body:
111
+ action_dict["body"] = self.body
112
+ return action_dict
113
+
114
+ def to_header(self):
115
+ header_str = f"action={self.action.value}, label={self.label}, url={self.url}, method={self.method}, clear={self.clear}"
116
+ if self.headers is not None:
117
+ headers = ""
118
+ for key, value in self.headers.items():
119
+ headers += f"headers.{key}={value}"
120
+ header_str += f", {headers}"
121
+ if self.body:
122
+ header_str += f", body={self.body}"
123
+ print(header_str)
124
+ return header_str
125
+
126
+
127
+ def send(
128
+ self,
129
+ message: str,
130
+ title: str = None,
131
+ priority: Optional[MessagePriority] = MessagePriority.DEFAULT,
132
+ tags: list = [],
133
+ actions: list[Union[ViewAction, BroadcastAction, HttpAction, None]] = [],
134
+ format_as_markdown: bool = False,
135
+ ):
136
+ """
137
+ Send a text based message to the server
138
+
139
+ :param message: The message to send
140
+ :param title: The title of the message. Optional
141
+ :param priority: The priority of the message. Optional, defaults to MessagePriority.DEFAULT
142
+ :param tags: A list of tags to attach to the message. Can be an emoji short code. Optional
143
+ :param format_as_markdown: If true, the message will be formatted as markdown. Optional
144
+ :param actions: A list of Actions objects to attach to the message. Optional
145
+ :return: The response from the server
146
+
147
+ :examples:
148
+ response = client.send(message="Example message")
149
+ response = client.send(message="Example message", title="Example title", priority=MessagePriority.HIGH, tags=["fire", "warning"])
150
+ response = client.send(message="*Example markdown*", format_as_markdown=True)
151
+ """
152
+ headers = {
153
+ "Title": title,
154
+ "Priority": priority.value,
155
+ "Tags": ",".join(tags),
156
+ "Markdown": "true" if format_as_markdown else "false",
157
+ }
158
+ if len(actions) > 0:
159
+ headers["Actions"] = " ; ".join([action.to_header() for action in actions])
160
+
161
+ response = json.loads(
162
+ requests.post(url=self.url, data=message, headers=headers, auth=self._auth).text
163
+ )
164
+ return response
165
+
166
+
167
+ def send_file(
168
+ self,
169
+ file: str,
170
+ title: str = None,
171
+ priority: Optional[MessagePriority] = MessagePriority.DEFAULT,
172
+ tags: list = [],
173
+ actions: list[Union[ViewAction, BroadcastAction, HttpAction, None]] = [],
174
+ ):
175
+ """
176
+ Send a file to the server
177
+
178
+ :param file_path: The path to the file to send.
179
+ :param title: The title of the file. Optional
180
+ :param priority: The priority of the message. Optional, defaults to MessagePriority.DEFAULT
181
+ :param tags: A list of tags to attach to the message. Can be an emoji short code. Optional
182
+ :param actions: A list of ActionButton objects to attach to the message. Optional
183
+ :return: The response from the server
184
+
185
+ :examples:
186
+ response = client.send_file(file_path="example.txt")
187
+ """
188
+ headers = {
189
+ "Title": title,
190
+ "Filename": file.split("/")[-1],
191
+ "Priority": priority.value,
192
+ "Tags": ",".join(tags),
193
+ "Actions": " ; ".join([action.to_header() for action in actions]),
194
+ }
195
+
196
+ with open(file, "rb") as file:
197
+ response = json.loads(
198
+ requests.post(
199
+ url=self.url, data=file, headers=headers, auth=self._auth
200
+ ).text
201
+ )
202
+ return response
@@ -1,69 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: python-ntfy
3
- Version: 0.1.0
4
- Summary: An ntfy library aiming for feature completeness
5
- Author: Matthew Cane
6
- Author-email: matthew.cane0@gmail.com
7
- Requires-Python: >=3.11,<4.0
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: Programming Language :: Python :: 3.11
10
- Requires-Dist: requests (>=2.31.0,<3.0.0)
11
- Description-Content-Type: text/markdown
12
-
13
- # ntfy.sh Python Library
14
-
15
- An easy-to-use ntfy python library. Aiming for full feature support.
16
-
17
- ## Quickstart
18
-
19
- 1. Install using pip with `pip3 install python-ntfy`
20
- 2. If you are using a server that requires auth, set the env vars
21
- 3. Import the library
22
-
23
- ```python
24
- from python_ntfy import NtfyClient
25
- ```
26
-
27
- 4. Create an `NtfyClient` instance with a topic
28
-
29
- ```python
30
- client = NtfyClient(topic="Your topic")
31
- ```
32
-
33
- 5. Send a message
34
-
35
- ```python
36
- client.send("Your message here")
37
- ```
38
-
39
- ## Supported Features
40
-
41
- - Username + password auth
42
- - Custom servers
43
- - Sending plaintext messages
44
- - Sending Markdown formatted text messages
45
- - Retrieving cached messages
46
- - Scheduled delivery
47
-
48
- ## Future Features
49
-
50
- - Access token auth
51
- - Email notifications
52
- - Tags
53
- - Action buttons
54
- - Send to multiple topics at once
55
-
56
- ## Test and Development
57
-
58
- This project uses Poetry.
59
-
60
- ### Tests
61
-
62
- This project is aiming for 95% code coverage. Any added features must include comprihensive tests.
63
-
64
- To run tests:
65
-
66
- 1. `poetry install --include test`
67
- 2. Add username and password for ntfy.sh to `.env`
68
- 3. `poetry run pytest --cov`
69
-
@@ -1,56 +0,0 @@
1
- # ntfy.sh Python Library
2
-
3
- An easy-to-use ntfy python library. Aiming for full feature support.
4
-
5
- ## Quickstart
6
-
7
- 1. Install using pip with `pip3 install python-ntfy`
8
- 2. If you are using a server that requires auth, set the env vars
9
- 3. Import the library
10
-
11
- ```python
12
- from python_ntfy import NtfyClient
13
- ```
14
-
15
- 4. Create an `NtfyClient` instance with a topic
16
-
17
- ```python
18
- client = NtfyClient(topic="Your topic")
19
- ```
20
-
21
- 5. Send a message
22
-
23
- ```python
24
- client.send("Your message here")
25
- ```
26
-
27
- ## Supported Features
28
-
29
- - Username + password auth
30
- - Custom servers
31
- - Sending plaintext messages
32
- - Sending Markdown formatted text messages
33
- - Retrieving cached messages
34
- - Scheduled delivery
35
-
36
- ## Future Features
37
-
38
- - Access token auth
39
- - Email notifications
40
- - Tags
41
- - Action buttons
42
- - Send to multiple topics at once
43
-
44
- ## Test and Development
45
-
46
- This project uses Poetry.
47
-
48
- ### Tests
49
-
50
- This project is aiming for 95% code coverage. Any added features must include comprihensive tests.
51
-
52
- To run tests:
53
-
54
- 1. `poetry install --include test`
55
- 2. Add username and password for ntfy.sh to `.env`
56
- 3. `poetry run pytest --cov`
@@ -1,48 +0,0 @@
1
- import json, requests
2
-
3
-
4
- def send(self, message: str, title: str = None, format_as_markdown: bool = False):
5
- """
6
- Send a text based message to the server
7
-
8
- :param message: The message to send
9
- :param title: The title of the message. Optional
10
- :param format_as_markdown: If true, the message will be formatted as markdown. Optional
11
- :return: The response from the server
12
-
13
- :examples:
14
- response = client.send(message="Example message")
15
- response = client.send(message="Example message", title="Example title")
16
- response = client.send(message="*Example markdown*", format_as_markdown=True)
17
- """
18
- headers = {
19
- "Title": title,
20
- "Markdown": "true" if format_as_markdown else "false",
21
- }
22
-
23
- response = json.loads(
24
- requests.post(url=self.url, data=message, headers=headers, auth=self._auth).text
25
- )
26
- return response
27
-
28
-
29
- def send_file(self, file: str, title: str = None):
30
- """
31
- Send a file to the server
32
-
33
- :param file_path: The path to the file to send
34
- :param title: The title of the file. Optional
35
- :return: The response from the server
36
-
37
- :examples:
38
- response = client.send_file(file_path="example.txt")
39
- """
40
- headers = {"Title": title, "Filename": file.split("/")[-1]}
41
-
42
- with open(file, "rb") as file:
43
- response = json.loads(
44
- requests.post(
45
- url=self.url, data=file, headers=headers, auth=self._auth
46
- ).text
47
- )
48
- return response