#!/usr/bin/env python
#coding:utf8
# Author : tuxpy
# Email : q8886888@qq.com
# Last modified : 2014-09-03 22:50:13
# Filename : weixin.py
# Description :
from config import render,kv_db
import os
import urllib2,json
import lxml
from lxml import etree
import time
import hashlib
import web
__all__ = ["WeixinInterface"]
class Public():
def _do_clear(self):
in_where = kv_db.get(self.fromUser + "_where")
if not in_where: # 如果当前在首页,则不需要清除相应记录
return None
if in_where.startswith("pc_"): # 在故障报修下的子菜单,就只清理下面的东西就行
kd_list = ["_content","_name","_phone","_where","_room","_when"]
if in_where.startswith("search_"):
kd_list = ["_where"] # 如果在搜索模式下,就只有清空当前位置信息,返回首页就行。
if in_where.startswith("login_"):
kd_list = ["_where","_user","_pwd", "_is_login"]
for item in kd_list:
kv_db.delete(self.fromUser + item)
def do_help(self):
self._do_clear()
help_mess=[
u'***输入以下指令.前的"符号"***',
u'"1.技术人员"——获取技术人员联系方式',
u'"2.最新公告"——获取协会的最近活动信息',
u'"3.电脑报修"——电脑出问题了?把问题提交给我们吧',
u'"4.搜索问题"——来我们的已解决故障的数据库中查找答案吧',
u'"#.退出当前模式,并显示帮助菜单"'
]
if kv_db.get(self.fromUser + "_is_login"):
help_mess.extend([
u'"bug.查看故障"——查看随机一个待解决故障',
u'"logout.退出登录"——注销当前账号'
])
return '\n'.join(help_mess)
class obj_pc(Public):
def __init__(self,line,fromUser):
self.line = line
self.fromUser = fromUser
def do_pc_(self):
kv_db.set(self.fromUser + "_where", "pc_content") # 改动当前位置,使用kd来判断当前位置
return u'请输入您遇到的电脑问题,至少要10个字哦~暂时不支持加图片。回复"#"退出故障提交模式'
def do_pc_content(self):
from submit import check_content
if check_content(self.line):
kv_db.set(self.fromUser + "_where", "pc_name")
kv_db.set(self.fromUser + "_content", self.line)
else:
return u"您输入的故障信息不能少于10个字哦~~请重新输入"
return u"请输入您的名字"
def do_pc_name(self):
from submit import check_name
if check_name(self.line):
kv_db.set(self.fromUser + "_where", "pc_phone")
kv_db.set(self.fromUser + "_name", self.line)
else:
return u"您输入的姓名不要太长,或太短哦"
return u"请输入您的联系方式"
def do_pc_phone(self):
from submit import check_phone
if check_phone(self.line):
kv_db.set(self.fromUser + "_where", "pc_room")
kv_db.set(self.fromUser + "_phone", self.line)
else:
return u"您输入的联系方式错误,请输入11位长号,或6位长号"
return u"您的寝室号?"
def do_pc_room(self):
kv_db.set(self.fromUser + "_where", "pc_when")
kv_db.set(self.fromUser + "_room", self.line)
return u"希望我们什么时候过去修?或者说你什么时候有空?"
def do_pc_when(self):
kv_db.set(self.fromUser + "_where", "pc_end") # 定位
kv_db.set(self.fromUser + "_when", self.line) # 存值
return self.__do_pc_data() # 到这信息都输入完毕,确定提交了
def do_pc_end(self):
if self.line.lower() != 'y':
self._do_clear()
return u"取消提交"
else:
if self.__do_pc_submit():
self._do_clear()
return u"提交成功"
else:
return u"提交失败,是否重试?"
def __do_pc_data(self): # 对提交问题的最后一个确定
data = [
u"故障: " + kv_db.get(self.fromUser + "_content"),
u"姓名: " + kv_db.get(self.fromUser + "_name"),
u"联系方式: " + kv_db.get(self.fromUser + "_phone"),
u"寝室号: " + kv_db.get(self.fromUser + "_room"),
u"维修时间: " + kv_db.get(self.fromUser + "_when"),
u"确定提交(回复'y'表示确定)?",
]
return '\n'.join(data)
def __do_pc_submit(self):
class Data(): # 为了和writeDb接口匹配
Content = kv_db.get(self.fromUser + "_content")
Name = kv_db.get(self.fromUser + "_name")
Phone = kv_db.get(self.fromUser + "_phone")
Room = kv_db.get(self.fromUser + "_room")
Time = kv_db.get(self.fromUser + "_when")
from submit import sendSubmit
data = Data()
try:
sendSubmit().writeDb(data)
return True
except:
return False
class obj_search(Public):
def __init__(self,line,fromUser):
self.line = line
self.fromUser = fromUser
def do_search_(self):
kv_db.set(self.fromUser + "_where", "search_content") # 改动当前位置,使用kd来判断当前位置
return u'请输入您的故障,2~30字\n(尽可以输得简单直白一点,不要拖泥带水。\
<a href="http://xxxxxxxxxxxx/help#search">使用帮助</a>)\n回复"#"退出搜索模式'
def do_search_content(self):
if not (2 <= len(self.line) <= 30):
return u"问题字数请控制在2~30"
else:
request = [u"问题: %s" % self.line,
u'答案: <a href="http://xxxxxxxxxx/sendKw?Kw=%s">点击查看</a>' % self.line,
u'回复"#"退出搜索模式',
]
return '\n'.join(request)
class obj_login(Public):
def __init__(self,line,fromUser):
self.line = line
self.fromUser = fromUser
def do_login_(self):
kv_db.set(self.fromUser + "_where", "login_user")
return u"请输入用户名"
def do_login_user(self):
kv_db.set(self.fromUser + "_where", "login_pwd")
kv_db.set(self.fromUser + "_user", self.line)
return u"请输入密码"
def do_login_pwd(self):
import hashlib
pwd = hashlib.md5(self.line).hexdigest()
kv_db.set(self.fromUser + "_pwd", pwd)
if check_login(self.fromUser):
kv_db.delete(self.fromUser + "_where")
kv_db.set(self.fromUser + "_is_login", True)
return u"登录成功"
else:
self._do_clear()
return u"登录失败"
def check_login(fromUser):
fromUser_user = kv_db.get(fromUser + '_user')
fromUser_pwd = kv_db.get(fromUser + '_pwd')
if fromUser_user and fromUser_pwd:
try:
from config import get_isLoginOk
uid = get_isLoginOk(fromUser_user, fromUser_pwd) # 用户uid
return True
except:
return False
else:
return False
class CommandHandler(Public):
def handle(self, line, fromUser):
self.fromUser = fromUser
cmd_list={ # 数字指令与文字指令对应的函数
u'1':"list", u'技术人员':"list",
u'2':"mess", u'最新公告':"mess",
u'3':"pc_", u'电脑报修':"pc_",
u'4':"search_", u'搜索问题':"search_", # 最后带_表示有子菜单
u'login':"login_",
u'logout':"logout",
u'bug':"bug",
u'#':"help",
}
in_where = kv_db.get(self.fromUser + "_where") # 获取当前所在位置。如果是首页,则是None
if in_where and line.strip() != '#': # 如果不在首页,则以当前所在位置,调用相应的函数。函数名是do_当前位置。
# self.line = line
command = in_where
else:
command = cmd_list.get(line.strip(),'help') # 如果指令不存在,则使用help,只在首页有效果
if command.startswith("pc_"):
obj = obj_pc(line,fromUser)
elif command.startswith("search_"):
obj = obj_search(line,fromUser)
elif command.startswith("login_"):
obj = obj_login(line, fromUser)
else:
obj = self
func = getattr(obj, 'do_' + command, None)
try:
request = func()
except TypeError:
request = self.do_help()
return request
def do_list(self):
from config import get_listDb
listDb = map(lambda x: ' '.join(x[1:]), get_listDb())
return "\n".join(listDb)
def do_mess(self):
from config import get_mess
mess = get_mess()
return mess
def do_logout(self):
kv_db.set(self.fromUser + "_where", "login_")
self._do_clear()
return u"账号已退出"
# 下面开始与bug有关..........................................
def do_bug(self):
if check_login(self.fromUser): # 同时具有查看是否登录成功效果
no, bugs_list = self.__get_bugs_list()
bugs_list_request = self.__get_bugs_request(bugs_list)
return u"共有%s个问题\n%s" % (no,'\n'.join(bugs_list_request))
else:
return u"请输入正确的用户凭证\nlogin——登录\nlogout——退出登录"
# 返回未解决问题的数量和未解决问题的列表,每个元素是 个tuple,里面是相关信息
def __get_bugs_list(self):
from config import get_bugsList
import random
bugslist = get_bugsList()
bugs_list = []
if bugslist.no > 0:
bug = random.choice(bugslist.nolist)
bugs_list.append((bug.PostTime,bug.Content,bug.Name,
bug.Phone,bug.Room,bug.Time))
return bugslist.no,bugs_list
def __get_bugs_request(self,bugs_list):
bugs_list_temp = [
u"提交时间: %s",
u"故障内容: %s",
u"姓名: %s",
u"联系方式: %s",
u"寝室: %s",
u"维修时间: %s",
]
bugs_list_request = []
for bug in bugs_list:
bugs_list_request.append('\n'.join([temp % value for temp,
value in zip(bugs_list_temp,bug)]))
return bugs_list_request
#................................................................
class WeixinInterface:
def __init__(self):
self.handler=CommandHandler()
def GET(self):
data = web.input()
signature=data.signature
timestamp=data.timestamp
nonce=data.nonce
echostr=data.echostr
#自己的token
token="xxxxxxxxxxxxxxxx"
#字典序排序
list=[token,timestamp,nonce]
list.sort()
sha1=hashlib.sha1()
map(sha1.update,list)
hashcode=sha1.hexdigest()
#sha1加密算法
#如果是来自微信的请求,则回复echostr
if hashcode == signature:
return echostr
def POST(self):
str_xml = web.data()
xml = etree.fromstring(str_xml)
msgType=xml.find("MsgType").text
fromUser=xml.find("FromUserName").text
toUser=xml.find("ToUserName").text
if msgType == "event":
mscontent = xml.find("Event").text
if mscontent == "subscribe":
content = u"#"
if msgType == "text":
content = xml.find("Content").text# 当msgType是event是无法找到Content的,所以这行代码,不能放在前面,要不会500
return render.reply_text(fromUser,toUser,int(time.time()),u"%s"%self.handler.handle(content,fromUser))
一部分代码,还好的设计整个网站的时候,接口都留出来了,直接拿来调用下就行了.初学web开发,写得有点乱。。
实现的功能有:查看我们社团的最新公告,查看维修电脑的技术人员,提交电脑故障,技术人员可以登录账号,登录后,可以查看用户提交的问题。类似短信营业厅的使用方式