# [Dingtalk-Webhook-Proxy](https://github.com/ConnectAI-E/Feishu-Webhook-Proxy/tree/dingding)
1. 将钉钉(dingtalk)webhook代理成websocket
2. 企业自建应用不用创建公网的回调地址,直接本地使用websocket客户端连上这个转发地址
# 设计
1. 使用nchan维护websocket的连接
2. 将钉钉的回调消息,抽取钉钉相关的头信息,外面包一层json,使用X-Request-Id作为唯一ID,推送给对应的channel
3. 客户端自己保存钉钉的密钥信息,从转发服务走的消息都是加密的。
4. 客户端调用钉钉其他接口,直接走自己的网络
## 安全性
1. 钉钉回调消息都是加密的,只能由websocket客户端自己解密,转发服务是透明的。
2. 如何确保自己的channel不会被别人恶意使用?
> 使用nginx basic auth,nchan支持auth_request,在对应的request里面使用basic auth就能做校验
## 实现
- [x] 部署一个nchan(openresty版本)
- [x] 配置一个internal的location,给内部转发钉钉消息使用
- [x] 配置一个location,作为钉钉webhook转发(处理消息转发逻辑)
# organization
> 使用一个organization对当前组织下面的所有bot进行管理
> 这样所有的消息可以通过`org_<name>`一个channel推送,这种模式下启动服务的时候可以不用提前注册所有的bot,可以动态的加入新的bot进去
- [x] 对org_<name>的channel增加basic auth
- [x] hook链接转发消息兼容organization
- [x] 新增一个支持organization的client
```
client = Client(bot1, bot2, org_name='org_lloyd', org_passwd='passwd')
```
# 使用
## python sdk
> 使用装饰器可以更简洁的通过一个回调函数处理消息
```
pip install ca-dingtalk-websocket
from connectai.dingtalk.websocket import Client
client = Client()
@client.on_bot_message(app_id='dingxxx', app_secret='xxx', agent_id='xxx', msgtype='text')
def on_message_callback1(bot, sessionwebhook, content, **kwargs):
text = content['content']
bot.reply(sessionWebhook, DingtalkTextMessage("reply: " + text))
client.start()
```
Raw data
{
"_id": null,
"home_page": "",
"name": "ca-dingtalk-websocket",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "",
"keywords": "Dingtalk,Webhook,Websocket,Bot",
"author": "lloydzhou@gmail.com",
"author_email": "",
"download_url": "https://files.pythonhosted.org/packages/b5/e7/32f323cfae7da6db0a57e96ec7a9a682cb77de25eefdd8869e9d7e2be5ba/ca-dingtalk-websocket-0.0.4.tar.gz",
"platform": null,
"description": "# [Dingtalk-Webhook-Proxy](https://github.com/ConnectAI-E/Feishu-Webhook-Proxy/tree/dingding)\n\n1. \u5c06\u9489\u9489(dingtalk)webhook\u4ee3\u7406\u6210websocket\n2. \u4f01\u4e1a\u81ea\u5efa\u5e94\u7528\u4e0d\u7528\u521b\u5efa\u516c\u7f51\u7684\u56de\u8c03\u5730\u5740\uff0c\u76f4\u63a5\u672c\u5730\u4f7f\u7528websocket\u5ba2\u6237\u7aef\u8fde\u4e0a\u8fd9\u4e2a\u8f6c\u53d1\u5730\u5740\n\n\n# \u8bbe\u8ba1\n1. \u4f7f\u7528nchan\u7ef4\u62a4websocket\u7684\u8fde\u63a5\n2. \u5c06\u9489\u9489\u7684\u56de\u8c03\u6d88\u606f\uff0c\u62bd\u53d6\u9489\u9489\u76f8\u5173\u7684\u5934\u4fe1\u606f\uff0c\u5916\u9762\u5305\u4e00\u5c42json\uff0c\u4f7f\u7528X-Request-Id\u4f5c\u4e3a\u552f\u4e00ID\uff0c\u63a8\u9001\u7ed9\u5bf9\u5e94\u7684channel\n3. \u5ba2\u6237\u7aef\u81ea\u5df1\u4fdd\u5b58\u9489\u9489\u7684\u5bc6\u94a5\u4fe1\u606f\uff0c\u4ece\u8f6c\u53d1\u670d\u52a1\u8d70\u7684\u6d88\u606f\u90fd\u662f\u52a0\u5bc6\u7684\u3002\n4. \u5ba2\u6237\u7aef\u8c03\u7528\u9489\u9489\u5176\u4ed6\u63a5\u53e3\uff0c\u76f4\u63a5\u8d70\u81ea\u5df1\u7684\u7f51\u7edc\n\n## \u5b89\u5168\u6027\n1. \u9489\u9489\u56de\u8c03\u6d88\u606f\u90fd\u662f\u52a0\u5bc6\u7684\uff0c\u53ea\u80fd\u7531websocket\u5ba2\u6237\u7aef\u81ea\u5df1\u89e3\u5bc6\uff0c\u8f6c\u53d1\u670d\u52a1\u662f\u900f\u660e\u7684\u3002\n2. \u5982\u4f55\u786e\u4fdd\u81ea\u5df1\u7684channel\u4e0d\u4f1a\u88ab\u522b\u4eba\u6076\u610f\u4f7f\u7528\uff1f\n> \u4f7f\u7528nginx basic auth\uff0cnchan\u652f\u6301auth_request\uff0c\u5728\u5bf9\u5e94\u7684request\u91cc\u9762\u4f7f\u7528basic auth\u5c31\u80fd\u505a\u6821\u9a8c\n\n\n## \u5b9e\u73b0\n- [x] \u90e8\u7f72\u4e00\u4e2anchan\uff08openresty\u7248\u672c\uff09\n- [x] \u914d\u7f6e\u4e00\u4e2ainternal\u7684location\uff0c\u7ed9\u5185\u90e8\u8f6c\u53d1\u9489\u9489\u6d88\u606f\u4f7f\u7528\n- [x] \u914d\u7f6e\u4e00\u4e2alocation\uff0c\u4f5c\u4e3a\u9489\u9489webhook\u8f6c\u53d1\uff08\u5904\u7406\u6d88\u606f\u8f6c\u53d1\u903b\u8f91\uff09\n\n\n# organization\n> \u4f7f\u7528\u4e00\u4e2aorganization\u5bf9\u5f53\u524d\u7ec4\u7ec7\u4e0b\u9762\u7684\u6240\u6709bot\u8fdb\u884c\u7ba1\u7406\n> \u8fd9\u6837\u6240\u6709\u7684\u6d88\u606f\u53ef\u4ee5\u901a\u8fc7`org_<name>`\u4e00\u4e2achannel\u63a8\u9001\uff0c\u8fd9\u79cd\u6a21\u5f0f\u4e0b\u542f\u52a8\u670d\u52a1\u7684\u65f6\u5019\u53ef\u4ee5\u4e0d\u7528\u63d0\u524d\u6ce8\u518c\u6240\u6709\u7684bot\uff0c\u53ef\u4ee5\u52a8\u6001\u7684\u52a0\u5165\u65b0\u7684bot\u8fdb\u53bb\n- [x] \u5bf9org_<name>\u7684channel\u589e\u52a0basic auth\n- [x] hook\u94fe\u63a5\u8f6c\u53d1\u6d88\u606f\u517c\u5bb9organization\n- [x] \u65b0\u589e\u4e00\u4e2a\u652f\u6301organization\u7684client\n\n```\nclient = Client(bot1, bot2, org_name='org_lloyd', org_passwd='passwd')\n```\n\n\n# \u4f7f\u7528\n\n## python sdk\n> \u4f7f\u7528\u88c5\u9970\u5668\u53ef\u4ee5\u66f4\u7b80\u6d01\u7684\u901a\u8fc7\u4e00\u4e2a\u56de\u8c03\u51fd\u6570\u5904\u7406\u6d88\u606f\n```\npip install ca-dingtalk-websocket\n\nfrom connectai.dingtalk.websocket import Client\n\nclient = Client()\n\n@client.on_bot_message(app_id='dingxxx', app_secret='xxx', agent_id='xxx', msgtype='text')\ndef on_message_callback1(bot, sessionwebhook, content, **kwargs):\n text = content['content']\n bot.reply(sessionWebhook, DingtalkTextMessage(\"reply: \" + text))\n\nclient.start()\n```\n\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "dingtalk client",
"version": "0.0.4",
"project_urls": {
"Code": "http://github.com/connectAI-E/Feishu-Webhook-Proxy",
"Documentation": "https://www.connectai-e.com",
"Issue tracker": "http://github.com/connectAI-E/Feishu-Webhook-Proxy/issues"
},
"split_keywords": [
"dingtalk",
"webhook",
"websocket",
"bot"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "b5e732f323cfae7da6db0a57e96ec7a9a682cb77de25eefdd8869e9d7e2be5ba",
"md5": "1c290a39054438b3d9d677c5f442928f",
"sha256": "26a3fe298f5ce6610c182d5b81487203ec9305d7f98349a3a408fbd97cc94502"
},
"downloads": -1,
"filename": "ca-dingtalk-websocket-0.0.4.tar.gz",
"has_sig": false,
"md5_digest": "1c290a39054438b3d9d677c5f442928f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 4154,
"upload_time": "2024-01-09T04:50:08",
"upload_time_iso_8601": "2024-01-09T04:50:08.385731Z",
"url": "https://files.pythonhosted.org/packages/b5/e7/32f323cfae7da6db0a57e96ec7a9a682cb77de25eefdd8869e9d7e2be5ba/ca-dingtalk-websocket-0.0.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-09 04:50:08",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "connectAI-E",
"github_project": "Feishu-Webhook-Proxy",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "ca-dingtalk-websocket"
}