diff --git a/README.md b/README.md index ca105c4..b81426d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # ipush -APP 推送通知。支持往 **钉钉群、飞书群、Lark 群、Bark、Chanify、PushDeer、PushPlus、Showdoc、息知** 推送消息。 +向 APP、微信平台推送通知。 +支持往 **Telegram、钉钉群、飞书群、Lark 群、Bark、Chanify、PushDeer、PushPlus、Showdoc、息知、Alertzy、Notify** 推送消息。 --- @@ -26,7 +27,7 @@ pip install -U ipush from ipush import Dingtalk notify = Dingtalk("token", "secret") -notify.send("ipush test") +notify.send("iPush test") ``` ## 支持平台 @@ -47,6 +48,8 @@ notify.send("ipush test") | 状态 | **国外**平台 | 官网 | 文档 | 备注 | | :------- | :----------- | :-------------------------------------------------------------------------------- | :--- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | | ✔ **荐** | **Telegram** | [https://core.telegram.org/bots/](https://core.telegram.org/bots/api#sendmessage) | - | 创建[Bot](https://t.me/BotFather)后,将 Bot 添加至群组或频道,再添加[获取 ChatId 的机器人进群组](https://t.me/getmyid_bot)(可移除),即可获得`ChatId` | +| ✔ | **Alertzy** | [https://alertzy.app/](https://alertzy.app/) | - | | +| ✔ | **Notify** | [https://notify.dev/](https://notify.dev/docs/quickstart) | - | 安装手机 APP,复制设备 ID(`Settings -> Device ID`),输入到 [`Playground`](https://notify.dev/playground),获取二维码,再使用手机 APP 扫描 | ## 开发 diff --git a/docs/README.md b/docs/README.md index f64cd79..d7df7c1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -107,3 +107,21 @@ notify.send("ipush test", "chat_id") notify.seturl("https://self-hosted") notify.send("ipush test custom url") ``` + +- **Alertzy** + +```python +from ipush import Alertzy + +notify = Alertzy("token") +notify.send("ipush test", "title") +``` + +- **Notify** + +```python +from ipush import Notify + +notify = Notify("token", "user_id") +notify.send("ipush test", "title") +``` diff --git a/pyproject.toml b/pyproject.toml index aae7608..7473002 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "ipush" -version = "0.3.0" -description = "APP 推送通知。支持往 钉钉群、飞书群、Lark 群、Bark、Chanify、PushDeer、PushPlus、Showdoc、息知 推送消息。" +version = "0.4.0" +description = "向 APP、微信平台推送通知。支持 Telegram、钉钉群、飞书群、Lark 群、Bark 等平台。" authors = [ { name = "Jetsung Chan", email = "jetsungchan@gmail.com" } ] @@ -10,7 +10,7 @@ dependencies = [ "lxml>=4.9.4", ] readme = "README.md" -keywords = ["push", "notify", "dingtalk", "feishu", "lark", "bark", "chanify", "pushdeer", "pushplus", "showdoc", "xizhi"] +keywords = ["push", "notify", "telegram", "dingtalk", "feishu", "lark", "bark", "chanify", "pushdeer", "pushplus", "showdoc", "xizhi"] requires-python = ">= 3.8" classifiers = [ 'Development Status :: 4 - Beta', @@ -37,6 +37,7 @@ classifiers = [ Homepage = "https://git.jetsung.com/idev/pypush" Documentation = "https://pypush.skiy.net/" Repository = "https://github.com/idevsig/pypush" +Download = "https://github.com/idevsig/pypush/releases" [build-system] requires = ["hatchling"] diff --git a/src/ipush/__init__.py b/src/ipush/__init__.py index 550d1f2..ee74db2 100644 --- a/src/ipush/__init__.py +++ b/src/ipush/__init__.py @@ -1,10 +1,12 @@ -from .notify.bark import Bark -from .notify.chanify import Chanify -from .notify.dingtalk import Dingtalk -from .notify.feishu import Feishu -from .notify.lark import Lark -from .notify.pushdeer import PushDeer -from .notify.pushplus import PushPlus -from .notify.showdoc import Showdoc -from .notify.telegram import Telegram -from .notify.xizhi import Xizhi +from .provider.alertzy import Alertzy +from .provider.bark import Bark +from .provider.chanify import Chanify +from .provider.dingtalk import Dingtalk +from .provider.feishu import Feishu +from .provider.lark import Lark +from .provider.notify import Notify +from .provider.pushdeer import PushDeer +from .provider.pushplus import PushPlus +from .provider.showdoc import Showdoc +from .provider.telegram import Telegram +from .provider.xizhi import Xizhi diff --git a/src/ipush/notify/__init__.py b/src/ipush/provider/__init__.py similarity index 100% rename from src/ipush/notify/__init__.py rename to src/ipush/provider/__init__.py diff --git a/src/ipush/notify/notify.py b/src/ipush/provider/_provider.py similarity index 88% rename from src/ipush/notify/notify.py rename to src/ipush/provider/_provider.py index fbe3e75..8b41b10 100644 --- a/src/ipush/notify/notify.py +++ b/src/ipush/provider/_provider.py @@ -2,11 +2,11 @@ from abc import abstractmethod """ -Notify 推送通知 +Provider 提供者 """ -class Notify(ABC): +class Provider(ABC): @abstractmethod def _signature(self): """ diff --git a/src/ipush/provider/alertzy.py b/src/ipush/provider/alertzy.py new file mode 100644 index 0000000..845e2f6 --- /dev/null +++ b/src/ipush/provider/alertzy.py @@ -0,0 +1,39 @@ +import json + +from ..utils.fetch import Fetch +from ._provider import Provider + + +class Alertzy(Provider): + """ + Alertzy通知 + """ + + def __init__(self, token=''): + self.token = token + + def _signature(self): + pass + + def _geturl(self): + """ + 生成请求的 URL + """ + return 'https://alertzy.app/send' + + def send(self, message, title=''): + """ + 发送通知 + :param message: 消息内容 + """ + req_url = self._geturl() + + req = Fetch() + + data = { + 'accountKey': self.token, + 'title': '新消息' if title == '' else title, + 'message': message, + } + req.post(req_url, data) + return req.response diff --git a/src/ipush/notify/bark.py b/src/ipush/provider/bark.py similarity index 88% rename from src/ipush/notify/bark.py rename to src/ipush/provider/bark.py index 64ae20e..92186b6 100644 --- a/src/ipush/notify/bark.py +++ b/src/ipush/provider/bark.py @@ -1,10 +1,10 @@ import json from ..utils.fetch import Fetch -from .notify import Notify +from ._provider import Provider -class Bark(Notify): +class Bark(Provider): """ Bark通知 """ @@ -39,7 +39,7 @@ def send(self, message, title=''): req.update_headers(headers) data = { - 'title': '' if title == '' else title, + 'title': '新消息' if title == '' else title, 'body': message, 'device_key': self.token, } diff --git a/src/ipush/notify/chanify.py b/src/ipush/provider/chanify.py similarity index 93% rename from src/ipush/notify/chanify.py rename to src/ipush/provider/chanify.py index 2df46b2..416c0e5 100644 --- a/src/ipush/notify/chanify.py +++ b/src/ipush/provider/chanify.py @@ -1,10 +1,10 @@ import json from ..utils.fetch import Fetch -from .notify import Notify +from ._provider import Provider -class Chanify(Notify): +class Chanify(Provider): """ Chanify通知 """ diff --git a/src/ipush/notify/dingtalk.py b/src/ipush/provider/dingtalk.py similarity index 95% rename from src/ipush/notify/dingtalk.py rename to src/ipush/provider/dingtalk.py index 65c43a1..5a675b5 100644 --- a/src/ipush/notify/dingtalk.py +++ b/src/ipush/provider/dingtalk.py @@ -3,10 +3,10 @@ from ..utils.fetch import Fetch from ..utils.helper import signature -from .notify import Notify +from ._provider import Provider -class Dingtalk(Notify): +class Dingtalk(Provider): """ 钉钉通知 """ diff --git a/src/ipush/notify/feishu.py b/src/ipush/provider/feishu.py similarity index 95% rename from src/ipush/notify/feishu.py rename to src/ipush/provider/feishu.py index 27ea2da..a9709d5 100644 --- a/src/ipush/notify/feishu.py +++ b/src/ipush/provider/feishu.py @@ -3,10 +3,10 @@ from ..utils.fetch import Fetch from ..utils.helper import signature -from .notify import Notify +from ._provider import Provider -class Feishu(Notify): +class Feishu(Provider): """ 飞书通知 """ diff --git a/src/ipush/notify/lark.py b/src/ipush/provider/lark.py similarity index 95% rename from src/ipush/notify/lark.py rename to src/ipush/provider/lark.py index 3586635..8037f42 100644 --- a/src/ipush/notify/lark.py +++ b/src/ipush/provider/lark.py @@ -3,10 +3,10 @@ from ..utils.fetch import Fetch from ..utils.helper import signature -from .notify import Notify +from ._provider import Provider -class Lark(Notify): +class Lark(Provider): """ Lark通知 """ diff --git a/src/ipush/provider/notify.py b/src/ipush/provider/notify.py new file mode 100644 index 0000000..96ae5d5 --- /dev/null +++ b/src/ipush/provider/notify.py @@ -0,0 +1,46 @@ +import json + +from ..utils.fetch import Fetch +from ._provider import Provider + + +class Notify(Provider): + """ + Notify通知 + """ + + def __init__(self, token='', user_id=''): + self.token = token + self.user_id = user_id + + def _signature(self): + pass + + def _geturl(self): + """ + 生成请求的 URL + """ + return 'https://notify.dev/api/v1/notify' + + def send(self, message, title=''): + """ + 发送通知 + :param message: 消息内容 + """ + req_url = self._geturl() + + headers = { + 'Content-Type': 'application/json', + 'Authorization': self.token, + } + req = Fetch() + req.update_headers(headers) + + data = { + 'user_id': self.user_id, + 'title': '新消息' if title == '' else title, + 'body': message, + } + data = json.dumps(data, indent=4) + req.post(req_url, data=data.encode('utf-8')) + return req.response diff --git a/src/ipush/notify/pushdeer.py b/src/ipush/provider/pushdeer.py similarity index 93% rename from src/ipush/notify/pushdeer.py rename to src/ipush/provider/pushdeer.py index 8f24751..e8c9c16 100644 --- a/src/ipush/notify/pushdeer.py +++ b/src/ipush/provider/pushdeer.py @@ -1,10 +1,10 @@ import json from ..utils.fetch import Fetch -from .notify import Notify +from ._provider import Provider -class PushDeer(Notify): +class PushDeer(Provider): """ PushDeer通知 """ diff --git a/src/ipush/notify/pushplus.py b/src/ipush/provider/pushplus.py similarity index 93% rename from src/ipush/notify/pushplus.py rename to src/ipush/provider/pushplus.py index ba69f03..e296a99 100644 --- a/src/ipush/notify/pushplus.py +++ b/src/ipush/provider/pushplus.py @@ -1,10 +1,10 @@ import json from ..utils.fetch import Fetch -from .notify import Notify +from ._provider import Provider -class PushPlus(Notify): +class PushPlus(Provider): """ PushPlus通知 """ diff --git a/src/ipush/notify/showdoc.py b/src/ipush/provider/showdoc.py similarity index 93% rename from src/ipush/notify/showdoc.py rename to src/ipush/provider/showdoc.py index 383f5e5..05483c2 100644 --- a/src/ipush/notify/showdoc.py +++ b/src/ipush/provider/showdoc.py @@ -1,10 +1,10 @@ import json from ..utils.fetch import Fetch -from .notify import Notify +from ._provider import Provider -class Showdoc(Notify): +class Showdoc(Provider): """ Showdoc通知 """ diff --git a/src/ipush/notify/telegram.py b/src/ipush/provider/telegram.py similarity index 94% rename from src/ipush/notify/telegram.py rename to src/ipush/provider/telegram.py index fed2943..7bc6ca4 100644 --- a/src/ipush/notify/telegram.py +++ b/src/ipush/provider/telegram.py @@ -1,10 +1,10 @@ import json from ..utils.fetch import Fetch -from .notify import Notify +from ._provider import Provider -class Telegram(Notify): +class Telegram(Provider): """ Telegram通知 """ diff --git a/src/ipush/notify/xizhi.py b/src/ipush/provider/xizhi.py similarity index 94% rename from src/ipush/notify/xizhi.py rename to src/ipush/provider/xizhi.py index dcbcba6..4bc6cf4 100644 --- a/src/ipush/notify/xizhi.py +++ b/src/ipush/provider/xizhi.py @@ -1,10 +1,10 @@ import json from ..utils.fetch import Fetch -from .notify import Notify +from ._provider import Provider -class Xizhi(Notify): +class Xizhi(Provider): """ Xizhi通知 """ diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..873dab6 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,16 @@ +import pytest + + +@pytest.fixture +def title(): + return 'iPush' + + +@pytest.fixture +def message(): + return 'PyPush test' + + +@pytest.fixture +def custom_message(): + return 'PyPush test custom url' diff --git a/tests/test_alertzy.py b/tests/test_alertzy.py new file mode 100644 index 0000000..f9c935e --- /dev/null +++ b/tests/test_alertzy.py @@ -0,0 +1,35 @@ +import os + +import pytest + +from ipush import Alertzy + + +@pytest.fixture +def access_token(): + token = os.environ.get('AlertzyToken') + return token + + +@pytest.mark.skipif( + not os.environ.get('AlertzyToken'), reason='Alertzy Token not provided' +) +def test_alertzy(access_token, message): + token = access_token + notify = Alertzy(token) + res = notify.send(message) + assert res.status_code == 200 + json = res.json() + assert json['response'] == 'success' + + +@pytest.mark.skipif( + not os.environ.get('AlertzyToken'), reason='Alertzy Token not provided' +) +def test_alertzy_title(access_token, title, message): + token = access_token + notify = Alertzy(token) + res = notify.send(message, title) + assert res.status_code == 200 + json = res.json() + assert json['response'] == 'success' diff --git a/tests/test_bark.py b/tests/test_bark.py index cddb38b..93e7534 100644 --- a/tests/test_bark.py +++ b/tests/test_bark.py @@ -13,20 +13,20 @@ def access_token(): @pytest.mark.skipif(not os.environ.get('BarkToken'), reason='Bark Token not provided') -def test_bark(access_token): +def test_bark(access_token, message): token, _ = access_token notify = Bark(token) - res = notify.send('pypush test') + res = notify.send(message) assert res.status_code == 200 json = res.json() assert json['code'] == 200 @pytest.mark.skipif(not os.environ.get('BarkToken'), reason='Bark Token not provided') -def test_bark_title(access_token): +def test_bark_title(access_token, message, title): token, _ = access_token notify = Bark(token) - res = notify.send('pypush test', 'ipush') + res = notify.send(message, title) assert res.status_code == 200 json = res.json() assert json['code'] == 200 @@ -36,11 +36,11 @@ def test_bark_title(access_token): not os.environ.get('BarkToken') or not os.environ.get('BarkCustomURL'), reason='Bark Token not provided', ) -def test_bark_custom_url(access_token): +def test_bark_custom_url(access_token, custom_message): token, custom_url = access_token notify = Bark(token) notify.seturl(custom_url) - res = notify.send('pypush test custom url') + res = notify.send(custom_message) assert res.status_code == 200 json = res.json() assert json['code'] == 200 diff --git a/tests/test_chanify.py b/tests/test_chanify.py index 3ae2f9c..d2cb949 100644 --- a/tests/test_chanify.py +++ b/tests/test_chanify.py @@ -15,10 +15,10 @@ def access_token(): @pytest.mark.skipif( not os.environ.get('ChanifyToken'), reason='Chanify Token not provided' ) -def test_chanify(access_token): +def test_chanify(access_token, message): token, _ = access_token notify = Chanify(token) - res = notify.send('pypush test') + res = notify.send(message) assert res.status_code == 200 @@ -26,9 +26,9 @@ def test_chanify(access_token): not os.environ.get('ChanifyToken') or not os.environ.get('ChanifyCustomURL'), reason='Chanify Token not provided', ) -def test_chanify_custom_url(access_token): +def test_chanify_custom_url(access_token, custom_message): token, custom_url = access_token notify = Chanify(token) notify.seturl(custom_url) - res = notify.send('pypush test custom url') + res = notify.send(custom_message) assert res.status_code == 200 diff --git a/tests/test_dingtalk.py b/tests/test_dingtalk.py index fed8a8f..e0fb207 100644 --- a/tests/test_dingtalk.py +++ b/tests/test_dingtalk.py @@ -15,10 +15,10 @@ def access_token(): @pytest.mark.skipif( not os.environ.get('DingtalkToken'), reason='Dingtalk Token not provided' ) -def test_dintalk(access_token): +def test_dintalk(access_token, message): token, secret = access_token notify = Dingtalk(token, secret) - res = notify.send('pypush test') + res = notify.send(message) assert res.status_code == 200 json = res.json() assert json['errcode'] == 0 diff --git a/tests/test_feishu.py b/tests/test_feishu.py index ef06707..3e2a401 100644 --- a/tests/test_feishu.py +++ b/tests/test_feishu.py @@ -15,10 +15,10 @@ def access_token(): @pytest.mark.skipif( not os.environ.get('FeishuToken'), reason='Feishu Token not provided' ) -def test_feishu(access_token): +def test_feishu(access_token, message): token, secret = access_token notify = Feishu(token, secret) - res = notify.send('pypush test') + res = notify.send(message) assert res.status_code == 200 json = res.json() assert json['code'] == 0 diff --git a/tests/test_lark.py b/tests/test_lark.py index 1b36ead..d0ffeab 100644 --- a/tests/test_lark.py +++ b/tests/test_lark.py @@ -13,10 +13,10 @@ def access_token(): @pytest.mark.skipif(not os.environ.get('LarkToken'), reason='Lark Token not provided') -def test_lark(access_token): +def test_lark(access_token, message): token, secret = access_token notify = Lark(token, secret) - res = notify.send('pypush test') + res = notify.send(message) assert res.status_code == 200 json = res.json() assert json['code'] == 0 diff --git a/tests/test_notify.py b/tests/test_notify.py new file mode 100644 index 0000000..112d327 --- /dev/null +++ b/tests/test_notify.py @@ -0,0 +1,38 @@ +import os + +import pytest + +from ipush import Notify + + +@pytest.fixture +def access_token(): + token = os.environ.get('NotifyToken') + user_id = os.environ.get('NotifyUserId') + return token, user_id + + +@pytest.mark.skipif( + not os.environ.get('NotifyToken') or not os.environ.get('NotifyUserId'), + reason='Notify Token not provided', +) +def test_notify(access_token, message): + token, user_id = access_token + notify = Notify(token, user_id) + res = notify.send(message) + assert res.status_code == 200 + json = res.json() + assert json['notification_id'] != '' + + +@pytest.mark.skipif( + not os.environ.get('NotifyToken') or not os.environ.get('NotifyUserId'), + reason='Notify Token not provided', +) +def test_notify_title(access_token, message, title): + token, user_id = access_token + notify = Notify(token, user_id) + res = notify.send(message, title) + assert res.status_code == 200 + json = res.json() + assert json['notification_id'] != '' diff --git a/tests/test_pushdeer.py b/tests/test_pushdeer.py index e159cbd..8bfe05a 100644 --- a/tests/test_pushdeer.py +++ b/tests/test_pushdeer.py @@ -15,10 +15,10 @@ def access_token(): @pytest.mark.skipif( not os.environ.get('PushDeerToken'), reason='PushDeer Token not provided' ) -def test_PushDeer(access_token): +def test_PushDeer(access_token, message): token, _ = access_token notify = PushDeer(token) - res = notify.send('pypush test') + res = notify.send(message) assert res.status_code == 200 json = res.json() assert json['code'] == 0 @@ -28,11 +28,11 @@ def test_PushDeer(access_token): not os.environ.get('PushDeerToken') or not os.environ.get('PushDeerCustomURL'), reason='PushDeer Token not provided', ) -def test_PushDeer_custom_url(access_token): +def test_PushDeer_custom_url(access_token, custom_message): token, custom_url = access_token notify = PushDeer(token) notify.seturl(custom_url) - res = notify.send('pypush test custom url') + res = notify.send(custom_message) assert res.status_code == 200 json = res.json() assert json['code'] == 0 diff --git a/tests/test_pushplus.py b/tests/test_pushplus.py index 6ba968c..784bf67 100644 --- a/tests/test_pushplus.py +++ b/tests/test_pushplus.py @@ -14,10 +14,10 @@ def access_token(): @pytest.mark.skipif( not os.environ.get('PushPlusToken'), reason='PushPlus Token not provided' ) -def test_pushplus(access_token): +def test_pushplus(access_token, message): token = access_token notify = PushPlus(token) - res = notify.send('pypush test') + res = notify.send(message) assert res.status_code == 200 json = res.json() assert json['code'] == 200 @@ -26,10 +26,10 @@ def test_pushplus(access_token): @pytest.mark.skipif( not os.environ.get('PushPlusToken'), reason='PushPlus Token not provided' ) -def test_pushplus_title(access_token): +def test_pushplus_title(access_token, message, title): token = access_token notify = PushPlus(token) - res = notify.send('pypush test', 'ipush') + res = notify.send(message, title) assert res.status_code == 200 json = res.json() assert json['code'] == 200 diff --git a/tests/test_showdoc.py b/tests/test_showdoc.py index 51f961b..33121e7 100644 --- a/tests/test_showdoc.py +++ b/tests/test_showdoc.py @@ -14,10 +14,10 @@ def access_token(): @pytest.mark.skipif( not os.environ.get('ShowdocToken'), reason='Showdoc Token not provided' ) -def test_showdoc(access_token): +def test_showdoc(access_token, message): token = access_token notify = Showdoc(token) - res = notify.send('pypush test') + res = notify.send(message) assert res.status_code == 200 json = res.json() assert json['error_code'] == 0 @@ -26,10 +26,10 @@ def test_showdoc(access_token): @pytest.mark.skipif( not os.environ.get('ShowdocToken'), reason='Showdoc Token not provided' ) -def test_showdoc_title(access_token): +def test_showdoc_title(access_token, message, title): token = access_token notify = Showdoc(token) - res = notify.send('pypush test', 'ipush') + res = notify.send(message, title) assert res.status_code == 200 json = res.json() assert json['error_code'] == 0 diff --git a/tests/test_telegram.py b/tests/test_telegram.py index 1e3525d..ffd7681 100644 --- a/tests/test_telegram.py +++ b/tests/test_telegram.py @@ -17,10 +17,10 @@ def access_token(): not os.environ.get('TelegramToken') or not os.environ.get('TelegramChatId'), reason='Telegram Token not provided', ) -def test_telegram(access_token): +def test_telegram(access_token, message): token, chat_id, _ = access_token notify = Telegram(token, chat_id) - res = notify.send('pypush test') + res = notify.send(message) assert res.status_code == 200 json = res.json() assert json['ok'] @@ -32,11 +32,11 @@ def test_telegram(access_token): or not os.environ.get('TelegramCustomURL'), reason='Telegram Token not provided', ) -def test_telegram_custom_url(access_token): +def test_telegram_custom_url(access_token, custom_message): token, chat_id, custom_url = access_token notify = Telegram(token, chat_id) notify.seturl(custom_url) - res = notify.send('pypush test custom url') + res = notify.send(custom_message) assert res.status_code == 200 json = res.json() assert json['ok'] diff --git a/tests/test_xizhi.py b/tests/test_xizhi.py index 947b86d..3dfefcd 100644 --- a/tests/test_xizhi.py +++ b/tests/test_xizhi.py @@ -12,20 +12,20 @@ def access_token(): @pytest.mark.skipif(not os.environ.get('XizhiToken'), reason='Xizhi Token not provided') -def test_xizhi(access_token): +def test_xizhi(access_token, message): token = access_token notify = Xizhi(token) - res = notify.send('pypush test') + res = notify.send(message) assert res.status_code == 200 json = res.json() assert json['code'] == 200 @pytest.mark.skipif(not os.environ.get('XizhiToken'), reason='Xizhi Token not provided') -def test_xizhi_title(access_token): +def test_xizhi_title(access_token, message, title): token = access_token notify = Xizhi(token) - res = notify.send('pypush test', 'ipush') + res = notify.send(message, title) assert res.status_code == 200 json = res.json() assert json['code'] == 200