django+python微信开发之四-最后的工作:消息服务类实现自动回复机器人
###消息服务类wechatService.py
之前的工作都差不多了,包括配置服务器,三种消息类型封装和对消息的处理(解析xml和转换成xml),最后是要根据不同的消息类型来作出反应了。
# -*- coding:utf-8 -*-
"""
# Author: Pegasus Wang (pegasuswang@qq.com, http://ningning.today)
# Created Time : Fri Feb 20 21:38:57 2015
# File Name: wechatService.py
# Description:
# :copyright: (c) 2015 by Pegasus Wang.
# :license: MIT, see LICENSE for more details.
"""
import time
from wechatUtil import MessageUtil
from wechatReply import TextReply
class WechatService(object):
"""process request"""
@staticmethod
def processRequest(request):
"""process different message types.
:param request: post request message
:return: None
"""
requestMap = MessageUtil.parseXml(request)
fromUserName = requestMap.get(u'FromUserName')
toUserName = requestMap.get(u'ToUserName')
createTime = requestMap.get(u'CreateTime')
msgType = requestMap.get(u'MsgType')
msgId = requestMap.get(u'MsgId')
textReply = TextReply()
textReply.setToUserName(fromUserName)
textReply.setFromUserName(toUserName)
textReply.setCreateTime(time.time())
textReply.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT)
if msgType == MessageUtil.REQ_MESSAGE_TYPE_TEXT:
content = requestMap.get('Content').decode('utf-8')
respContent = u'您发送的是文本消息: ' + content
elif msgType == MessageUtil.REQ_MESSAGE_TYPE_IMAGE:
respContent = u'您发送的是图片消息!'
elif msgType == MessageUtil.REQ_MESSAGE_TYPE_VOICE:
respContent = u'您发送的是语音消息!'
elif msgType == MessageUtil.REQ_MESSAGE_TYPE_VIDEO:
respContent = u'您发送的是视频消息!'
elif msgType == MessageUtil.REQ_MESSAGE_TYPE_LOCATION:
respContent = u'您发送的是地理位置消息!'
elif msgType == MessageUtil.REQ_MESSAGE_TYPE_LINK:
respContent = u'您发送的是链接消息!'
elif msgType == MessageUtil.REQ_MESSAGE_TYPE_EVENT:
eventType = requestMap.get(u'Event')
if eventType == MessageUtil.EVENT_TYPE_SUBSCRIBE:
respContent = u'^_^谢谢您的关注!'
elif eventType == MessageUtil.EVENT_TYPE_UNSUBSCRIBE:
pass
elif eventType == MessageUtil.EVENT_TYPE_SCAN:
# TODO
pass
elif eventType == MessageUtil.EVENT_TYPE_LOCATION:
# TODO
pass
elif eventType == MessageUtil.EVENT_TYPE_CLICK:
# TODO
pass
textReply.setContent(respContent)
respXml = MessageUtil.class2xml(textReply)
return respXml
代码也非常简单,就是根据不同的消息类型进行处理。
最近又发现了一个好玩的自动回复图灵机器人,我们可以调用它的接口实现我们的文本消息自动回复,比如回复个“笑话”它就会给你发送一个笑话,要注意的是它经常发一些少儿不宜的笑话。更改后的代码如下(改动的地方代码中会说明):
# -*- coding:utf-8 -*-
"""
# Author: Pegasus Wang (pegasuswang@qq.com, http://ningning.today)
# Created Time : Fri Feb 20 21:38:57 2015
# File Name: wechatService.py
# Description:
# :copyright: (c) 2015 by Pegasus Wang.
# :license: MIT, see LICENSE for more details.
"""
import json
import time
import urllib
import urllib2
from wechatUtil import MessageUtil
from wechatReply import TextReply
# add a robot auto reply class
class RobotService(object):
"""Auto reply robot service"""
KEY = 'd92d20bc1d8bb3cff585bf746603b2a9' # change to your key
url = 'http://www.tuling123.com/openapi/api'
@staticmethod
def auto_reply(req_info):
query = {'key': RobotService.KEY, 'info': req_info.encode('utf-8')}
headers = {'Content-type': 'text/html', 'charset': 'utf-8'}
data = urllib.urlencode(query)
req = urllib2.Request(RobotService.url, data)
f = urllib2.urlopen(req).read()
return json.loads(f).get('text').replace('<br>', '\n')
class WechatService(object):
"""process request"""
@staticmethod
def processRequest(request):
"""process different message types.
:param request: post request message
:return: None
"""
requestMap = MessageUtil.parseXml(request)
fromUserName = requestMap.get(u'FromUserName')
toUserName = requestMap.get(u'ToUserName')
createTime = requestMap.get(u'CreateTime')
msgType = requestMap.get(u'MsgType')
msgId = requestMap.get(u'MsgId')
textReply = TextReply()
textReply.setToUserName(fromUserName)
textReply.setFromUserName(toUserName)
textReply.setCreateTime(time.time())
textReply.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT)
if msgType == MessageUtil.REQ_MESSAGE_TYPE_TEXT:
content = requestMap.get('Content').decode('utf-8') # note: decode first
# respContent = u'您发送的是文本消息:' + content
# change to auto_reply(content)
respContent = RobotService.auto_reply(content)
elif msgType == MessageUtil.REQ_MESSAGE_TYPE_IMAGE:
respContent = u'您发送的是图片消息!'
elif msgType == MessageUtil.REQ_MESSAGE_TYPE_VOICE:
respContent = u'您发送的是语音消息!'
elif msgType == MessageUtil.REQ_MESSAGE_TYPE_VIDEO:
respContent = u'您发送的是视频消息!'
elif msgType == MessageUtil.REQ_MESSAGE_TYPE_LOCATION:
respContent = u'您发送的是地理位置消息!'
elif msgType == MessageUtil.REQ_MESSAGE_TYPE_LINK:
respContent = u'您发送的是链接消息!'
elif msgType == MessageUtil.REQ_MESSAGE_TYPE_EVENT:
eventType = requestMap.get(u'Event')
if eventType == MessageUtil.EVENT_TYPE_SUBSCRIBE:
respContent = u'^_^谢谢您的关注,本公众号由王宁宁开发(python2.7+django1.4),如果你有兴趣继续开发,' \
u'可以联系我,就当打发时间了.'
elif eventType == MessageUtil.EVENT_TYPE_UNSUBSCRIBE:
pass
elif eventType == MessageUtil.EVENT_TYPE_SCAN:
# TODO
pass
elif eventType == MessageUtil.EVENT_TYPE_LOCATION:
# TODO
pass
elif eventType == MessageUtil.EVENT_TYPE_CLICK:
# TODO
pass
textReply.setContent(respContent)
respXml = MessageUtil.class2xml(textReply)
return respXml
"""
if msgType == 'text':
content = requestMap.get('Content')
# TODO
elif msgType == 'image':
picUrl = requestMap.get('PicUrl')
# TODO
elif msgType == 'voice':
mediaId = requestMap.get('MediaId')
format = requestMap.get('Format')
# TODO
elif msgType == 'video':
mediaId = requestMap.get('MediaId')
thumbMediaId = requestMap.get('ThumbMediaId')
# TODO
elif msgType == 'location':
lat = requestMap.get('Location_X')
lng = requestMap.get('Location_Y')
label = requestMap.get('Label')
scale = requestMap.get('Scale')
# TODO
elif msgType == 'link':
title = requestMap.get('Title')
description = requestMap.get('Description')
url = requestMap.get('Url')
"""
###编写wechat的views.py
最后为了更好地组织代码,我们在wechat这个app文件家里再建立两个文件views.py和urls.py,后面我们再把wechat的urls加入到mysite里边。
# -*- coding:utf-8 -*-
"""
# Author: Pegasus Wang (pegasuswang@qq.com, http://ningning.today)
# Created Time : Wed Feb 18 18:18:10 2015
# File Name: views.py
# Description:
# :copyright: (c) 2015 by Pegasus Wang.
# :license: MIT, see LICENSE for more details.
"""
# Create your views here.
from django.http import HttpResponse
from django.views.generic.base import View
from .wechatUtil import checkSignature
from .wechatService import WechatService
class WechatInterfaceView(View):
def get(self, request):
echostr = request.GET.get(u'echostr', None)
if checkSignature(request):
return HttpResponse(echostr)
def post(self, request):
return HttpResponse(WechatService.processRequest(request))
这里定义了一个通用视图类,用来处理微信公众账号发过来的请求。
###编写wechat的urls.py
# -*- coding:utf-8 -*-
"""
# Author: Pegasus Wang (pegasuswang@qq.com, http://ningning.today)
# Created Time : Fri Feb 20 22:31:30 2015
# File Name: urls.py
# Description:
# :copyright: (c) 2015 by Pegasus Wang.
# :license: MIT, see LICENSE for more details.
"""
from django.conf.urls import patterns, url
from django.views.decorators.csrf import csrf_exempt
from wechat import views
urlpatterns = patterns('',
url(r'^$', csrf_exempt(views.WechatInterfaceView.as_view())),
)
###编写mysite的urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^wechat/', include('wechat.urls', namespace='wechat')),
)
###大功告成
到这里所有的代码就编写完成了,为了像模像样,我们再项目里加上LISENCE和README.md文件。看看最终的项目结构,用tree 2命令
,2是文件夹名:
1 | 2 |
用svn上传所有代码到sae服务器,然后就可以测试了。效果如下:
如果结果不符合预期,你可以参考鹦鹉学舌那篇文章用curl或者python的requests模块模拟微信服务器发送post请求到你的sae服务器,观察sae返回的结果就知道什么问题了。