github-webhook与企业WeChat-robort中间件开发
WebHook
什么是WebHook
最典型的例子:当你发送一条朋友圈,微信的服务器会把你的这条朋友圈同步到你所有好友的客户端(要是你屏蔽人了就是给服务器列出了特别名单)
这还是 客户端 - 服务器 模式的逆转模式
传统方法中,一般是客户端向服务器发出 请求 ,服务器给予客户端 响应 (这叫客户机拉取请求)
在 WebHook 范式下,服务器更新所需提供的资源,然后自动将其作为更新发送到客户端(服务器是在推数据),客户端不是请求者,而是被动接收方
应用场景
对于第三方平台验权、登陆等 没有前端界面做中转的场景,或者强安全要求的支付场景等,适合用 Webhook 做数据主动推送,说白了就是在前端无从参与,或者因为前端安全问题不适合参与时,就是 Webhook 的场景;很显然 Webhook 也不是 Http 的替代品,不过的确是一种新的 前后端交互方式。
企业微信机器人
工作原理
机器人就相当于一个webhook,创建者可在机器人的详情页查看机器人特有的WebHookURL,向这个链接发送一个 http post 请求,即可实现给该群组发送消息。
要特别注意
机器人的 webhookurl 要保护好,不要分享到那些公开可查阅的地方,否则可能会有人控制机器人发送垃圾信息了。
发送信息的格式
text类型
1
2
3
4
5
6
7
8
{
"msgtype": "text",
"text": {
"content": "Hello EveryOne",
"mentioned_list": ["要艾特的人"],
"mentioned_mobile_list": ["要艾特的人的电话号"]
}
}
markdown类型
1
2
3
4
5
6
7
8
9
{
"msgtype": "markdown",
"markdon": {
"content": "## 仓库提交记录 \n
> 提交人:XXX \n
> 提交人邮箱:XXX \n
..."
}
}
常见的是这两种,还有文件类型和图片类型
python请求发送的格式
代码举例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import requests #requests 包主要就是负责发送get或者post请求
def wechat_roboot(message_data):
post_headers = {'Content-Type': 'application/json'}
post_url = "{企业微信机器人的WebHookUrl}"
post_data = {
"msgtype": "markdown",
"markdown": {
"content": "## 仓库提交记录" + "\n"
+ "<font color=\"comment\">仓库名称</font>:" + repo_name + "\n"
+ "<font color=\"comment\">描述</font>:" + repo_description + "\n"
+ "> 提交人:" + committer_name + "\n"
+ "> 提交人邮箱:" + committer_email + "\n"
+ "> 提交简介:" + msg + "\n"
+ "> 提交时间:" + time + "\n"
+ "[更新位置仓库链接](" + url + ")" + "\n"
}
}
ret = requests.post(
url = post_url,
headers = post_headers,
json = post_data
)
#可讲响应结果打印
print(ret.text)
http 请求头 “Content-Type” 常见的媒体格式类型请看菜鸟教程
GitHub WebHook
工作原理
当仓库有push、pull等操作后,会向定义的webhookUrl发送post请求
参考文章
服务器环境搭建
端口配置
面板配置端口
打开云服务器,找到安全组,放行5000端口(5555端口等预定义的远程调试端口不能用哦)
服务器内部打开该端口防火墙
1
2
3
4
systemctl start firewalld.service
firewall-cmd --zone=public --add-port=5000/tcp --permanent
systemctl restart firewalld.service
firewall-cmd --reload
这里不打开也有可能无法访问该端口
python环境配置
虚拟环境
-
用pip安装virtualenvwrapper
-
执行命令
1
vim ~/ .bashrc
-
在最后加上
1 2
export WORKON_HOME=$HOME/.virtualenvs source /usr/local/bin/virtualenvwrapper.sh
-
运行
1
source ~/.bashrc
-
执行
1
mkvirtualenv '虚拟环境名称' # python2 环境
-
执行
1
mkvirtualenv -p python3 '虚拟环境名称' # python3环境
更多虚拟环境执行命令请看code口德
编写代码
导入需要的包
1
2
3
4
5
import json #用于处理后期传入的json数据
import time #获取当前时间等等
import requests #发送get/post请求
from flask import Flask, request, jsonify #flask是主要的包
from gevent import pywsgi #必须通过wsgi启动webapp,外网才能访问
编写webApp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
app = Flask(__name__)
#外网访问时'ip地址/'可以得到 'hello world' 的响应
@app.route('/')
def hello_world():
return 'Hello World!'
#外网访问'ip地址/martin'时,触发下面的get_post()方法
@app.route('/martin', methods=["GET","POST"])
def get_post():
#设置访问钥匙(防止别人恶意发送垃圾消息)
if request.args.get("key") == '任意编写乱码':
data = request.get_data() #取得由外网发送过来的数据
new_json = json.loads(data) #json字符串转换为json数据
new_data = trans_coding(new_json) #调用筛选代码筛选有用信息
try:
wechat_roboot(new_data) #筛选完之后将有用信息发送给企业微信机器人
except:
return "Forward faild"
return "Forward Successfull!"
return "No Rules"
功能函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 企业微信机器人推送消息
def wechat_roboot(message_data):
data = {
"msgtype": "markdown",
"markdown": {
"content": "你要发送的数据"
}
}
ret = requests.post(
url="企业微信机器人连接",
headers=headers,
json=data
)
print(ret.text) #发送成功后的响应
# 时间格式化
def time_format(old_time):
new_time_year = old_time[0:10]
new_time_date = old_time[11:19]
return new_time_year + " " + new_time_date
# 筛选需要的数据
def trans_coding(new_json):
#筛选出想要的数据,打包好
...
#...
return new_data
主函数调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if __name__ == '__main__':
#打开本机的5000端口
server = pywsgi.WSGIServer(('0.0.0.0', 5000),app)
print(time.asctime(),'Serve started on port',5000)
try:
#保证程序始终在运行
server.serve_forever()
if(close==True):
raise
except KeyboardInterrupt:
server.server_close()
print(time.asctime(),"server Stopped")
except:
server.server_close()
print(time.asctime(),"server Stopped")
部署代码
创建虚拟环境
进入工作空间 workon my_env
1
mkvirtualenv -p python3 my_env
放置代码
1
2
3
4
5
6
7
#创建一个工作空间放置代码 (可要可不要,看个人习惯)
mkdir pythonWorkSpace
#进入刚刚创建的工作空间
cd pythonWorkSpace
#创建一个python文件
vim robort.py
#将代码粘贴到编辑器中
运行代码
1
2
3
4
5
6
7
8
9
#保存并退出编辑模式
#挂载python程序
python robort.py &
#查看进程是否正常
ps -ef|grep python
#如果有之前占用此端口的程序为结束可能会报错
#此时可以找到占用端口进程的pid通过 `kill pid` 杀死进程
#测试无问题后可将程序在后台挂载
nuhup python robort.py &
遇到问题
虚拟环境
1
Utunbu配置虚拟环境,virtualenv 安装时如果pip不是最新版,下载的时候会丢包
外网访问服务器时无法得到响应
服务器端放行端口
- 在服务器面板找到安全组,添加一个安全组,选择端口号,协议为TCP协议。
- 连通ssh修改防火墙配置:
1
2
3
4
systemctl start firewalld.service
firewall-cmd --zone=public --add-port=5000/tcp --permanent
systemctl restart firewalld.service
firewall-cmd --reload
一定要保证面板放通的端口号与ssh打开的端口号一致,我开通的是5000
通过wsgi来启动flask
方法一:(我用的)
1
2
3
4
5
from gevent import pywsgi
if __name__ == '__main__':
server = pywsgi.WSGIServer(('0.0.0.0', 5000), app)
server.serve_forever()
方法二:
1
2
3
4
5
from wsgiref.simple_server import make_server
if __name__ == '__main__':
server = make_server('', 5000, app)
server.serve_forever()
这两个方法的底层都是wsgi,只是后期封装不太一样,我也不知道怎么比较好坏
报OSError:[Errno 98] Address already in use错
此错误表示端口被占用,未释放或者程序没有正常结束
通过
1
ps -ef|grep python # 找到端口号占用的对应的python进程的pid
再通过
1
kill pid # 杀死进程