[R.M.C] 用python实现微信控制电脑端虾米音乐(3)

接上篇 用python实现微信控制电脑端虾米音乐(2)

上篇里介绍了如何接受用户发送到微信的消息,做了个简单的echo程序,这次我们来讲SAE中完整的代码写完。

一、指令的处理以及储存

也就是图上画红圈的部分:

我们给weixinInterface.py里的POST方法中加上处理指令的代码(weixinInterface.py改后完整的代码见文章末尾):

# 检测是否为命令(是否为"cmd "开头)
if content.startswith("cmd "):
    command = content[4:] # 截取指令的内容
    mc = pylibmc.Client() # 获取Memcache实例
    old = mc.get(fromUser + "_cmd") # 获取该用户缓存的指令
    if not old: # 如果没有缓存的指令,设置成空列表
        old = []
    
    # 将之前缓存的指令与新的指令形成的列表
    # 存放在"用户名_cmd"的键下
    mc.set(fromUser + "_cmd", old + [command])
    content = "命令[{}]已接收".format(command) # 修改回复的内容
Memcache在这里的作用:

先说明一下Memcache在这里的作用,SAE是我们的我们的网络应用,每次我们访问一次我们网络应用的URL就会运行一遍我们的代码,所以如果我们只是单纯的创建一个变量将我们的数据储存在内存中,下一次访问的时候,这些数据都会重置,不能储存下来,所以我们需要Memcache这个缓存服务来讲我们需要储存的数据储存下来,以便之后使用。还有我们创建的这个网络应用时选的是共享环境,所以每次运行我们代码的服务器可能都不一样,所以需要Memcache来缓存我们的数据。Memcache是以键值对的形式来管理数据的,就像Python中的字典一样。

在Memcache中储存命令的形式:

将用户的所有命令已字符串的形式存在列表中,并将该列表储存在Memcache中以”用户名_cmd”的键下

处理命令的具体步骤如下:
  1. 判断用户发送的消息是否为”cmd空格”开头
  2. 截取指令部分即cmd空格之后的内容
  3. 获取pylibmc实例(pylibmc库是一个让Python管理Memcache的库)
  4. 从Memcache中获取用户的旧指令
  5. 将新指令连接到旧指令列表中,储存进Memcache

二、客户端指令的接收

思路

这里让客户端使用GET方法来获取用户储存在SAE的指令。指令以json的形式传递,接收到的将是json形式的列表,列表内以字符串的形式存放着所有未获得的指令。这里为了简单起见,定义:如果使用GET方法访问我们SAE的URL时,有usercmd这个参数表明要获取以这个参数为名称的用户所存放的所有指令。当然这里存在一点安全隐患,因为任何人都可以随意的访问我们这个URL来读取用户的指令列表,可以采取一些简单的加密来提高安全性,这里简单起见就不做这些处理了。

SAE端的设置

首先在weixinInterface.py的GET方法中添加(weixinInterface.py改后完整的代码见文章末尾):

try: # 来自电脑客户端的请求
    user = params.usercmd # 获取usercmd参数
    mc = pylibmc.Client() # 获取Memcache实例
    cmdlist = mc.get(user + "_cmd") # 获取用户对应的所有指令
    if not cmdlist:
        cmdlist = []
    mc.set(user + "_cmd", []) # 将用户对应的指令列表清空
    return json.dumps(cmdlist) # 将指令列表以json的格式作为响应返回

except: # 错误请求
    pass

 

客户端的设置

再在电脑本地创建一个client.py文件,作为我们的客户端程序,之后将使用它来访问我们的SAE来获取指令,我们先写个简单的测试程序:

import requests
import json
import time


if __name__ == "__main__":
    while True:
        user = "LeiZiTing" # 这里填入你企业微信中用户的名称,可以在企业微信的成员管理中找到
        # 访问SAE,并添加参数usercmd
        r = requests.get("http://timpcfanwx01.applinzi.com/weixin?usercmd=" + user)
        cmdlist = json.loads(r.text) # 读取获得的json数据,得到指令列表
        for command in cmdlist: # 处理指令列表中每一条指令
            print(time.strftime("%D %H:%M:%S ") + command)
        time.sleep(1) # 休息一秒钟~

运行我们的测试程序,然后在微信上发以”cmd空格”开头的指令试试看~

效果图:

我们成功将微信上发的内容传递到电脑上了,接下来我们就可以做任何我们想做的事了。

随时随地使用微信给自己的电脑发送指令,通过python完成一些简单的任务,是不是很棒棒xD

以下附上修改后完整的weixinInterface.py:(修改的部分使用注释标明)

# -*- coding: utf-8 -*-
import hashlib
import web
import lxml
import time
import os
import urllib2, json, urllib
from lxml import etree
from WXBizMsgCrypt import WXBizMsgCrypt
import pylibmc # 需要在SAE中申请创建Memcached
import json # 处理json

sCorpID = 'YOUR_CORPID' # 企业微信的CorpID
AGENTID_RMC = 'YOUR_AGENTID' # 应用的AgentId
SECRET_RMC = 'YOUR_SECRET' # 应用的Secret
sToken = 'Token00000'
sEncodingAESKey = 'EncodingAESKey00000000000000000000000000000'


class WeixinInterface:
    def __init__(self):
        self.app_root = os.path.dirname(__file__)
        self.templates_root = os.path.join(self.app_root, 'templates')
        self.render = web.template.render(self.templates_root)
        self.wxcpt = WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID)

    def GET(self):
        # 获取URL参数
        params = web.input()

        try: # 来自微信的请求
            signature = params.msg_signature
            timestamp = params.timestamp
            nonce = params.nonce
            echostr = params.echostr
            ret, echostr = self.wxcpt.VerifyURL(signature, timestamp, nonce, echostr)
            if ret == 0:
                return echostr
           	
        except:
            try: # 来自电脑客户端的请求
                user = str(params.usercmd) # 获取usercmd参数,并转化为str类型(原本是unicode类型)
                mc = pylibmc.Client() # 获取Memcache实例
                cmdlist = mc.get(user + "_cmd") # 获取用户对应的所有指令
                if not cmdlist:
                    cmdlist = []
                mc.set(user + "_cmd", []) # 将用户对应的指令列表清空
                print cmdlist
                return json.dumps(cmdlist) # 将指令列表以json的格式作为响应返回
            
            except: # 错误请求
                pass
                
        
    def POST(self):
        # 获取URL参数
        params = web.input()

        # 获取POST的数据
        data = web.data()

        signature = params.msg_signature
        timestamp = params.timestamp
        nonce = params.nonce

        # 解密消息
        ret, msg = self.wxcpt.DecryptMsg(data, signature, timestamp, nonce)
        if ret != 0:
            print "ERR: DecryptMsg ret: " + str(ret)
            return ''

        xml = etree.fromstring(msg)
        content = xml.find("Content").text
        msgType = xml.find("MsgType").text
        fromUser = xml.find("FromUserName").text
        toUser = xml.find("ToUserName").text
        msgid = xml.find("MsgId").text
        
        # 检测是否为命令(是否为"cmd "开头)
        if content.startswith("cmd "):
            command = content[4:] # 截取指令的内容
            mc = pylibmc.Client() # 获取Memcache实例
            old = mc.get(fromUser + "_cmd") # 获取该用户缓存的指令
            if not old: # 如果没有缓存的指令,设置成空列表
                old = []
            # 将之前缓存的指令与新的指令形成的列表
            # 存放在"用户名_cmd"的键下
            mc.set(fromUser + "_cmd", old + [command])
            content = "命令[{}]已接收".format(command) # 修改回复的内容

        msg_xml = self.render.reply_text(fromUser, toUser, timestamp, content, msgid, AGENTID_RMC)
        # 将产生的数据加密
        ret, encryptmsg = self.wxcpt.EncryptMsg(str(msg_xml), nonce, timestamp)
        if ret != 0:
            print "ERR: EncryptMsg ret: " + str(ret)
            return ''
        # 将加密的数据返回给用户
        return encryptmsg

 

待续未完~

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据