github的webhook虽然可以直接定向到企微的机器人链接,但如果想要拿到我们需要的部分数据,所传送的数据就需要通过一个中间件进行一系列筛选

WebHook

什么是WebHook

最典型的例子:当你发送一条朋友圈,微信的服务器会把你的这条朋友圈同步到你所有好友的客户端(要是你屏蔽人了就是给服务器列出了特别名单)

这还是 客户端 - 服务器 模式的逆转模式

传统方法中,一般是客户端向服务器发出 请求 ,服务器给予客户端 响应 (这叫客户机拉取请求)

WebHook 范式下,服务器更新所需提供的资源,然后自动将其作为更新发送到客户端(服务器是在推数据),客户端不是请求者,而是被动接收方

应用场景

对于第三方平台验权、登陆等 没有前端界面做中转的场景,或者强安全要求的支付场景等,适合用 Webhook 做数据主动推送,说白了就是在前端无从参与,或者因为前端安全问题不适合参与时,就是 Webhook 的场景;很显然 Webhook 也不是 Http 的替代品,不过的确是一种新的 前后端交互方式

企业微信机器人

工作原理

机器人就相当于一个webhook,创建者可在机器人的详情页查看机器人特有的WebHookURL,向这个链接发送一个 http post 请求,即可实现给该群组发送消息。

要特别注意

机器人的 webhookurl 要保护好,不要分享到那些公开可查阅的地方,否则可能会有人控制机器人发送垃圾信息了。

发送信息的格式

text类型

{
 "msgtype": "text",
 "text": {
     "content": "Hello EveryOne",
     "mentioned_list": ["要艾特的人"],
     "mentioned_mobile_list": ["要艾特的人的电话号"] 
 }
}

markdown类型

{
 "msgtype": "markdown",
 "markdon": {
     "content": "## 仓库提交记录 \n
        			> 提交人:XXX \n
        			> 提交人邮箱:XXX \n
        			..."
    }
}

常见的是这两种,还有文件类型和图片类型

python请求发送的格式

代码举例

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请求

参考文章

MayerBin

服务器环境搭建

端口配置

面板配置端口

打开云服务器,找到安全组,放行5000端口(5555端口等预定义的远程调试端口不能用哦)

服务器内部打开该端口防火墙

systemctl start firewalld.service 
firewall-cmd --zone=public --add-port=5000/tcp --permanent
systemctl restart firewalld.service
firewall-cmd --reload

这里不打开也有可能无法访问该端口

python环境配置

虚拟环境

  1. 用pip安装virtualenvwrapper

  2. 执行命令

    vim ~/ .bashrc
    
  3. 在最后加上

    export WORKON_HOME=$HOME/.virtualenvs
    source /usr/local/bin/virtualenvwrapper.sh
    
  4. 运行

    source ~/.bashrc
    
  5. 执行

    mkvirtualenv '虚拟环境名称' # python2 环境
    
  6. 执行

    mkvirtualenv -p python3 '虚拟环境名称' # python3环境
    

更多虚拟环境执行命令请看code口德

编写代码

导入需要的包

import json #用于处理后期传入的json数据
import time #获取当前时间等等
import requests #发送get/post请求 
from flask import Flask, request, jsonify #flask是主要的包
from gevent import pywsgi #必须通过wsgi启动webapp,外网才能访问

编写webApp


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"

功能函数

# 企业微信机器人推送消息
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

主函数调用

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

mkvirtualenv -p python3 my_env

放置代码

#创建一个工作空间放置代码 (可要可不要,看个人习惯)
mkdir pythonWorkSpace
#进入刚刚创建的工作空间
cd pythonWorkSpace
#创建一个python文件
vim robort.py
#将代码粘贴到编辑器中

运行代码

#保存并退出编辑模式
#挂载python程序 
python robort.py &  
#查看进程是否正常 
ps -ef|grep python
#如果有之前占用此端口的程序为结束可能会报错
#此时可以找到占用端口进程的pid通过 `kill pid` 杀死进程
#测试无问题后可将程序在后台挂载 
nuhup python robort.py &

遇到问题

虚拟环境

Utunbu配置虚拟环境,virtualenv 安装时如果pip不是最新版,下载的时候会丢包

外网访问服务器时无法得到响应

服务器端放行端口

  1. 在服务器面板找到安全组,添加一个安全组,选择端口号,协议为TCP协议。
  2. 连通ssh修改防火墙配置:
systemctl start firewalld.service 
firewall-cmd --zone=public --add-port=5000/tcp --permanent
systemctl restart firewalld.service
firewall-cmd --reload

一定要保证面板放通的端口号与ssh打开的端口号一致,我开通的是5000

通过wsgi来启动flask

方法一:(我用的)

from gevent import pywsgi

if __name__ == '__main__':
    server = pywsgi.WSGIServer(('0.0.0.0', 5000), app)
    server.serve_forever()

方法二:

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错

此错误表示端口被占用,未释放或者程序没有正常结束

通过

ps -ef|grep python # 找到端口号占用的对应的python进程的pid

再通过

kill pid #  杀死进程
photo