mirror of
https://github.com/whyour/qinglong.git
synced 2026-04-29 00:45:11 +08:00
Add OpeniLink notification channel (#2988)
* Initial plan * Add OpeniLink notification channel support Agent-Logs-Url: https://github.com/whyour/qinglong/sessions/c80b4882-1bd7-4ffe-9180-cd3220da5986 Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> * Add context_token and hub_url to OpeniLink notification channel Agent-Logs-Url: https://github.com/whyour/qinglong/sessions/a5e66f5a-dab8-4a65-96ca-960d35fa9d50 Co-authored-by: whyour <22700758+whyour@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>
This commit is contained in:
parent
07bf0c705b
commit
66700ebe1a
|
|
@ -20,6 +20,7 @@ export enum NotificationMode {
|
|||
'chronocat' = 'Chronocat',
|
||||
'ntfy' = 'ntfy',
|
||||
'wxPusherBot' = 'wxPusherBot',
|
||||
'openiLink' = 'openiLink',
|
||||
}
|
||||
|
||||
abstract class NotificationBaseInfo {
|
||||
|
|
@ -161,6 +162,12 @@ export class WxPusherBotNotification extends NotificationBaseInfo {
|
|||
public wxPusherBotUids = '';
|
||||
}
|
||||
|
||||
export class OpeniLinkNotification extends NotificationBaseInfo {
|
||||
public openiLinkAppToken = '';
|
||||
public openiLinkHubUrl = '';
|
||||
public openiLinkContextToken = '';
|
||||
}
|
||||
|
||||
export interface NotificationInfo
|
||||
extends GoCqHttpBotNotification,
|
||||
GotifyNotification,
|
||||
|
|
@ -182,4 +189,5 @@ export interface NotificationInfo
|
|||
ChronocatNotification,
|
||||
LarkNotification,
|
||||
NtfyNotification,
|
||||
WxPusherBotNotification {}
|
||||
WxPusherBotNotification,
|
||||
OpeniLinkNotification {}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ export default class NotificationService {
|
|||
['chronocat', this.chronocat],
|
||||
['ntfy', this.ntfy],
|
||||
['wxPusherBot', this.wxPusherBot],
|
||||
['openiLink', this.openiLink],
|
||||
]);
|
||||
|
||||
private title = '';
|
||||
|
|
@ -858,4 +859,35 @@ export default class NotificationService {
|
|||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
private async openiLink() {
|
||||
const { openiLinkAppToken, openiLinkHubUrl, openiLinkContextToken } =
|
||||
this.params;
|
||||
const baseUrl = openiLinkHubUrl?.replace(/\/$/, '') || 'https://hub.openilink.com';
|
||||
const url = `${baseUrl}/bot/v1/message/send`;
|
||||
const body: Record<string, string> = {
|
||||
type: 'text',
|
||||
content: `${this.title}\n\n${this.content}`,
|
||||
};
|
||||
if (openiLinkContextToken) {
|
||||
body.context_token = openiLinkContextToken;
|
||||
}
|
||||
try {
|
||||
const res = await httpClient.post(url, {
|
||||
...this.gotOption,
|
||||
json: body,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${openiLinkAppToken}`,
|
||||
},
|
||||
});
|
||||
if (res.ok) {
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(JSON.stringify(res));
|
||||
}
|
||||
} catch (error: any) {
|
||||
throw new Error(error.response ? error.response.body : error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,4 +259,13 @@ export WEBHOOK_METHOD=""
|
|||
## 支持 text/plain、application/json、multipart/form-data、application/x-www-form-urlencoded
|
||||
export WEBHOOK_CONTENT_TYPE=""
|
||||
|
||||
## 23. OpeniLink
|
||||
## 官方文档: https://openilink.com/docs/hub/apps
|
||||
## 在 OpeniLink Hub 后台安装 App 后获取 app_token
|
||||
export OPENILINK_APP_TOKEN=""
|
||||
## OpeniLink Hub 地址,默认为 https://hub.openilink.com,自建 Hub 时填写自己的地址
|
||||
export OPENILINK_HUB_URL=""
|
||||
## OpeniLink 的 context_token,用于标识消息会话上下文,可从消息事件中获取
|
||||
export OPENILINK_CONTEXT_TOKEN=""
|
||||
|
||||
## 其他需要的变量,脚本中需要的变量使用 export 变量名= 声明即可
|
||||
|
|
|
|||
|
|
@ -151,6 +151,11 @@ const push_config = {
|
|||
WXPUSHER_APP_TOKEN: '', // wxpusher 的 appToken
|
||||
WXPUSHER_TOPIC_IDS: '', // wxpusher 的 主题ID,多个用英文分号;分隔 topic_ids 与 uids 至少配置一个才行
|
||||
WXPUSHER_UIDS: '', // wxpusher 的 用户ID,多个用英文分号;分隔 topic_ids 与 uids 至少配置一个才行
|
||||
|
||||
// 官方文档: https://openilink.com/docs/hub/apps
|
||||
OPENILINK_APP_TOKEN: '', // OpeniLink 的 app_token,在 OpeniLink Hub 后台安装 App 后获取
|
||||
OPENILINK_HUB_URL: '', // OpeniLink Hub 地址,默认为 https://hub.openilink.com,自建 Hub 时填写自己的地址
|
||||
OPENILINK_CONTEXT_TOKEN: '', // OpeniLink 的 context_token,用于标识消息会话上下文,可从消息事件中获取
|
||||
};
|
||||
|
||||
for (const key in push_config) {
|
||||
|
|
@ -1408,6 +1413,54 @@ function wxPusherNotify(text, desp) {
|
|||
});
|
||||
}
|
||||
|
||||
function openiLinkNotify(text, desp) {
|
||||
return new Promise((resolve) => {
|
||||
const { OPENILINK_APP_TOKEN, OPENILINK_HUB_URL, OPENILINK_CONTEXT_TOKEN } =
|
||||
push_config;
|
||||
if (OPENILINK_APP_TOKEN) {
|
||||
const baseUrl = OPENILINK_HUB_URL
|
||||
? OPENILINK_HUB_URL.replace(/\/$/, '')
|
||||
: 'https://hub.openilink.com';
|
||||
const body = {
|
||||
type: 'text',
|
||||
content: `${text}\n\n${desp}`,
|
||||
};
|
||||
if (OPENILINK_CONTEXT_TOKEN) {
|
||||
body.context_token = OPENILINK_CONTEXT_TOKEN;
|
||||
}
|
||||
const options = {
|
||||
url: `${baseUrl}/bot/v1/message/send`,
|
||||
body: JSON.stringify(body),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${OPENILINK_APP_TOKEN}`,
|
||||
},
|
||||
timeout,
|
||||
};
|
||||
|
||||
$.post(options, (err, resp, data) => {
|
||||
try {
|
||||
if (err) {
|
||||
console.log('OpeniLink 发送通知消息失败!\n', err);
|
||||
} else {
|
||||
if (data.ok) {
|
||||
console.log('OpeniLink 发送通知消息成功!');
|
||||
} else {
|
||||
console.log(`OpeniLink 发送通知消息异常:${data.error}`);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
$.logErr(e, resp);
|
||||
} finally {
|
||||
resolve(data);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function parseString(input, valueFormatFn) {
|
||||
const regex = /(\w+):\s*((?:(?!\n\w+:).)*)/g;
|
||||
const matches = {};
|
||||
|
|
@ -1538,6 +1591,7 @@ async function sendNotify(text, desp, params = {}) {
|
|||
qmsgNotify(text, desp), // 自定义通知
|
||||
ntfyNotify(text, desp), // Ntfy
|
||||
wxPusherNotify(text, desp), // wxpusher
|
||||
openiLinkNotify(text, desp), // OpeniLink
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -135,6 +135,10 @@ push_config = {
|
|||
'WXPUSHER_APP_TOKEN': '', # wxpusher 的 appToken 官方文档: https://wxpusher.zjiecode.com/docs/ 管理后台: https://wxpusher.zjiecode.com/admin/
|
||||
'WXPUSHER_TOPIC_IDS': '', # wxpusher 的 主题ID,多个用英文分号;分隔 topic_ids 与 uids 至少配置一个才行
|
||||
'WXPUSHER_UIDS': '', # wxpusher 的 用户ID,多个用英文分号;分隔 topic_ids 与 uids 至少配置一个才行
|
||||
|
||||
'OPENILINK_APP_TOKEN': '', # OpeniLink 的 app_token,在 OpeniLink Hub 后台安装 App 后获取 官方文档: https://openilink.com/docs/hub/apps
|
||||
'OPENILINK_HUB_URL': '', # OpeniLink Hub 地址,默认为 https://hub.openilink.com,自建 Hub 时填写自己的地址
|
||||
'OPENILINK_CONTEXT_TOKEN': '', # OpeniLink 的 context_token,用于标识消息会话上下文,可从消息事件中获取
|
||||
}
|
||||
# fmt: on
|
||||
|
||||
|
|
@ -898,6 +902,43 @@ def wxpusher_bot(title: str, content: str) -> None:
|
|||
print(f"wxpusher 推送失败!错误信息:{response.get('msg')}")
|
||||
|
||||
|
||||
def openilink(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 OpeniLink 推送消息。
|
||||
支持的环境变量:
|
||||
- OPENILINK_APP_TOKEN: 在 OpeniLink Hub 后台安装 App 后获取的 app_token
|
||||
- OPENILINK_HUB_URL: OpeniLink Hub 地址,默认为 https://hub.openilink.com
|
||||
- OPENILINK_CONTEXT_TOKEN: 消息会话上下文 token,可从消息事件中获取
|
||||
"""
|
||||
if not push_config.get("OPENILINK_APP_TOKEN"):
|
||||
return
|
||||
|
||||
print("OpeniLink 服务启动")
|
||||
|
||||
base_url = (
|
||||
push_config.get("OPENILINK_HUB_URL", "").rstrip("/")
|
||||
or "https://hub.openilink.com"
|
||||
)
|
||||
url = f"{base_url}/bot/v1/message/send"
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f'Bearer {push_config.get("OPENILINK_APP_TOKEN")}',
|
||||
}
|
||||
data = {
|
||||
"type": "text",
|
||||
"content": f"{title}\n\n{content}",
|
||||
}
|
||||
if push_config.get("OPENILINK_CONTEXT_TOKEN"):
|
||||
data["context_token"] = push_config.get("OPENILINK_CONTEXT_TOKEN")
|
||||
|
||||
response = requests.post(url=url, json=data, headers=headers).json()
|
||||
|
||||
if response.get("ok"):
|
||||
print("OpeniLink 推送成功!")
|
||||
else:
|
||||
print(f'OpeniLink 推送失败!错误信息:{response.get("error")}')
|
||||
|
||||
|
||||
def parse_headers(headers):
|
||||
if not headers:
|
||||
return {}
|
||||
|
|
@ -1063,6 +1104,8 @@ def add_notify_function():
|
|||
push_config.get("WXPUSHER_TOPIC_IDS") or push_config.get("WXPUSHER_UIDS")
|
||||
):
|
||||
notify_function.append(wxpusher_bot)
|
||||
if push_config.get("OPENILINK_APP_TOKEN"):
|
||||
notify_function.append(openilink)
|
||||
if not notify_function:
|
||||
print(f"无推送渠道,请检查通知变量是否正确")
|
||||
return notify_function
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ export default {
|
|||
{ value: 'pushPlus', label: 'PushPlus' },
|
||||
{ value: 'wePlusBot', label: intl.get('微加机器人') },
|
||||
{ value: 'wxPusherBot', label: 'wxPusher' },
|
||||
{ value: 'openiLink', label: 'OpeniLink' },
|
||||
{ value: 'chat', label: intl.get('群晖chat') },
|
||||
{ value: 'email', label: intl.get('邮箱') },
|
||||
{ value: 'lark', label: intl.get('飞书机器人') },
|
||||
|
|
@ -387,6 +388,27 @@ export default {
|
|||
required: false,
|
||||
},
|
||||
],
|
||||
openiLink: [
|
||||
{
|
||||
label: 'openiLinkAppToken',
|
||||
tip: intl.get(
|
||||
'OpeniLink的app_token,在OpeniLink Hub后台安装App后获取,参考 https://openilink.com/docs/hub/apps',
|
||||
),
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: 'openiLinkHubUrl',
|
||||
tip: intl.get(
|
||||
'OpeniLink Hub地址,默认为 https://hub.openilink.com,自建Hub时填写自己的地址',
|
||||
),
|
||||
},
|
||||
{
|
||||
label: 'openiLinkContextToken',
|
||||
tip: intl.get(
|
||||
'OpeniLink的context_token,用于标识消息会话上下文,可从消息事件中获取',
|
||||
),
|
||||
},
|
||||
],
|
||||
lark: [
|
||||
{
|
||||
label: 'larkKey',
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user