def TEMPLATE(self): if 'account' in self._args: return to_text( """ <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[transfer_customer_service]]></MsgType> <TransInfo> <KfAccount><![CDATA[{account}]]></KfAccount> </TransInfo> </xml> """ ) else: return to_text( """ <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[transfer_customer_service]]></MsgType> </xml> """ )
def test_to_text(): assert to_text(6) == six.text_type(6) assert to_text(b"aa") == "aa" assert to_text("cc") == "cc" if six.PY2: assert to_text(u"喵") == u"喵" assert to_text("喵") == u"喵"
def render(self): return to_text(self.TEMPLATE.format( title=to_text(self.title), description=to_text(self.description), img=to_text(self.img), url=to_text(self.url) ))
def search(message): if to_text(message.content) == to_text('status'): url = 'http://127.0.0.1:8000/api/status' result = requests.get(url).json() return result['total'] url = 'http://127.0.0.1:8000/api/search/%s' % message.content result = requests.get(url).json() return_value = '' return_value += '搜索到 %d 个结果:\n' % result['total'] max_page = result['max_page'] result = requests.get('%s/page/1' % url).json() for r in result['results']: return_value += '=' * 5 return_value += '\n' r['last_seen'] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(r['last_seen'])) r['length'] = '%dMB' % int(r['length'] / 1024 / 1024) return_value += '名称: %s\n' % r['title'] return_value += '大小: %s\n' % r['length'] return_value += '记录时间: %s\n' % r['last_seen'] return_value += '详情页: http://www.shapaozi.me/detail/%s\n' % r[ 'infohash'] return_value += '=' * 5 return_value += '\n' if max_page > 1: return_value += '更多结果请点击: http://www.shapaozi.me/search/%s' % message.content return return_value
def render(self): items = [] for article in self._articles: items.append(ArticlesReply.ITEM_TEMPLATE.format( title=to_text(article.title), description=to_text(article.description), img=to_text(article.img), url=to_text(article.url) )) self._args["items"] = ''.join(items) self._args["count"] = len(items) if "content" not in self._args: self._args["content"] = '' return ArticlesReply.TEMPLATE.format(**self._args)
def render(self): items = [] for article in self._articles: items.append( ArticlesReply.ITEM_TEMPLATE.format( title=to_text(article.title), description=to_text(article.description), img=to_text(article.img), url=to_text(article.url))) self._args["items"] = ''.join(items) self._args["count"] = len(items) if "content" not in self._args: self._args["content"] = '' return ArticlesReply.TEMPLATE.format(**self._args)
class ArticlesReply(WeChatReply): TEMPLATE = to_text(""" <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[news]]></MsgType> <Content><![CDATA[{content}]]></Content> <ArticleCount>{count}</ArticleCount> <Articles>{items}</Articles> <FuncFlag>{flag}</FuncFlag> </xml> """) ITEM_TEMPLATE = to_text(""" <item> <Title><![CDATA[{title}]]></Title> <Description><![CDATA[{description}]]></Description> <PicUrl><![CDATA[{img}]]></PicUrl> <Url><![CDATA[{url}]]></Url> </item> """) def __init__(self, message=None, star=False, **kwargs): super(ArticlesReply, self).__init__(message, star, **kwargs) self._articles = [] def add_article(self, article): if len(self._articles) >= 10: raise AttributeError("Can't add more than 10 articles" " in an ArticlesReply") else: self._articles.append(article) def render(self): items = [] for article in self._articles: items.append( ArticlesReply.ITEM_TEMPLATE.format( title=to_text(article.title), description=to_text(article.description), img=to_text(article.img), url=to_text(article.url))) self._args["items"] = ''.join(items) self._args["count"] = len(items) if "content" not in self._args: self._args["content"] = '' return ArticlesReply.TEMPLATE.format(**self._args)
def process_args(self, kwargs): args = defaultdict(str) for k, v in kwargs.items(): if is_string(v): v = to_text(v) args[k] = v return args
class ArticlesReply(WeChatReply): TEMPLATE = to_text(""" <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[news]]></MsgType> <Content><![CDATA[{content}]]></Content> <ArticleCount>{count}</ArticleCount> <Articles>{items}</Articles> </xml> """) def __init__(self, message=None, **kwargs): super(ArticlesReply, self).__init__(message, **kwargs) self._articles = [] def add_article(self, article): if len(self._articles) >= 10: raise AttributeError("Can't add more than 10 articles" " in an ArticlesReply") else: self._articles.append(article) def render(self): items = [] for article in self._articles: items.append(article.render()) self._args["items"] = ''.join(items) self._args["count"] = len(items) if "content" not in self._args: self._args["content"] = '' return ArticlesReply.TEMPLATE.format(**self._args)
def add_filter(self, func, rules): """ 为 BaseRoBot 添加一个 ``filter handler``。 :param func: 如果 rules 通过,则处理该消息的 handler。 :param rules: 一个 list,包含要匹配的字符串或者正则表达式。 :return: None """ if not callable(func): raise ValueError("{} is not callable".format(func)) if not isinstance(rules, list): raise ValueError("{} is not list".format(rules)) if len(rules) > 1: for x in rules: self.add_filter(func, [x]) else: target_content = rules[0] if isinstance(target_content, six.string_types): target_content = to_text(target_content) def _check_content(message): return message.content == target_content elif is_regex(target_content): def _check_content(message): return target_content.match(message.content) else: raise TypeError("%s is not a valid rule" % target_content) argc = len(signature(func).parameters.keys()) @self.text def _f(message, session=None): if _check_content(message): return func(*[message, session][:argc])
class TransferCustomerServiceReply(WeChatReply): TEMPLATE = to_text(""" <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[transfer_customer_service]]></MsgType> </xml> """)
def test_filter(): import re import werobot.testing robot = WeRoBot(SESSION_STORAGE=False) @robot.filter("喵") def _1(): return "喵" assert len(robot._handlers["text"]) == 1 @robot.filter(re.compile(to_text(".*?呵呵.*?"))) def _2(): return "哼" assert len(robot._handlers["text"]) == 2 @robot.text def _3(): return "汪" assert len(robot._handlers["text"]) == 3 tester = werobot.testing.WeTest(robot) assert tester.send_xml(_make_xml("啊"))._args['content'] == u"汪" assert tester.send_xml(_make_xml("啊呵呵"))._args['content'] == u"哼" assert tester.send_xml(_make_xml("喵"))._args['content'] == u"喵" try: os.remove(os.path.abspath("werobot_session")) except OSError: pass robot = WeRoBot(SESSION_STORAGE=False) @robot.filter("帮助", "跪求帮助", re.compile("(.*?)help.*?")) def _(message, session, match): if match and match.group(1) == u"小姐姐": return "本小姐就帮你一下" return "就不帮" assert len(robot._handlers["text"]) == 3 @robot.text def _4(): return "哦" assert len(robot._handlers["text"]) == 4 tester = werobot.testing.WeTest(robot) assert tester.send_xml(_make_xml("啊"))._args['content'] == u"哦" assert tester.send_xml(_make_xml("帮助"))._args['content'] == u"就不帮" assert tester.send_xml(_make_xml("跪求帮助"))._args['content'] == u"就不帮" assert tester.send_xml(_make_xml("ooohelp"))._args['content'] == u"就不帮" assert tester.send_xml( _make_xml("小姐姐help"))._args['content'] == u"本小姐就帮你一下"
def test_filter(): import re import werobot.testing robot = WeRoBot() @robot.filter("喵") def _(): return "喵" assert len(robot._handlers["text"]) == 1 @robot.filter(re.compile(to_text(".*?呵呵.*?"))) def _(): return "哼" assert len(robot._handlers["text"]) == 2 @robot.text def _(): return "汪" def _make_xml(content): return """ <xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[%s]]></Content> <MsgId>1234567890123456</MsgId> </xml> """ % content tester = werobot.testing.WeTest(robot) assert tester.send_xml(_make_xml("啊")) == "汪" assert tester.send_xml(_make_xml("啊呵呵")) == "哼" assert tester.send_xml(_make_xml("喵")) == "喵" robot = WeRoBot() @robot.filter("帮助", "跪求帮助", re.compile(".*?help.*?")) def _(): return "就不帮" assert len(robot._handlers["text"]) == 3 @robot.text def _(): return "哦" tester = werobot.testing.WeTest(robot) assert tester.send_xml(_make_xml("啊")) == "哦" assert tester.send_xml(_make_xml("帮助")) == "就不帮" assert tester.send_xml(_make_xml("跪求帮助")) == "就不帮" assert tester.send_xml(_make_xml("ooohelp")) == "就不帮"
def test_filter(): import re import werobot.testing robot = WeRoBot(SESSION_STORAGE=False) @robot.filter("喵") def _1(): return "喵" assert len(robot._handlers["text"]) == 1 @robot.filter(re.compile(to_text(".*?呵呵.*?"))) def _2(): return "哼" assert len(robot._handlers["text"]) == 2 @robot.text def _3(): return "汪" assert len(robot._handlers["text"]) == 3 tester = werobot.testing.WeTest(robot) assert tester.send_xml(_make_xml("啊"))._args['content'] == u"汪" assert tester.send_xml(_make_xml("啊呵呵"))._args['content'] == u"哼" assert tester.send_xml(_make_xml("喵"))._args['content'] == u"喵" try: os.remove(os.path.abspath("werobot_session")) except OSError: pass robot = WeRoBot(SESSION_STORAGE=False) @robot.filter("帮助", "跪求帮助", re.compile("(.*?)help.*?")) def _(message, session, match): if match and match.group(1) == u"小姐姐": return "本小姐就帮你一下" return "就不帮" assert len(robot._handlers["text"]) == 3 @robot.text def _4(): return "哦" assert len(robot._handlers["text"]) == 4 tester = werobot.testing.WeTest(robot) assert tester.send_xml(_make_xml("啊"))._args['content'] == u"哦" assert tester.send_xml(_make_xml("帮助"))._args['content'] == u"就不帮" assert tester.send_xml(_make_xml("跪求帮助"))._args['content'] == u"就不帮" assert tester.send_xml(_make_xml("ooohelp"))._args['content'] == u"就不帮" assert tester.send_xml(_make_xml("小姐姐help") )._args['content'] == u"本小姐就帮你一下"
def encrypt_message(self, reply, timestamp=None, nonce=None): """ 加密微信回复 :param reply: 加密前的回复 :type reply: WeChatReply 或 XML 文本 :return: 加密后的回复文本 """ if hasattr(reply, "render"): reply = reply.render() timestamp = timestamp or to_text(int(time.time())) nonce = nonce or generate_token(5) encrypt = to_text(self.prp_crypto.encrypt(reply, self.app_id)) signature = get_signature(self.token, timestamp, nonce, encrypt) return to_text( self.ENCRYPTED_MESSAGE_XML.format(encrypt=encrypt, signature=signature, timestamp=timestamp, nonce=nonce))
class TextReply(WeChatReply): TEMPLATE = to_text(""" <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[{content}]]></Content> </xml> """)
def test_string_entry(): assert isinstance(t.test_string, six.text_type) assert t.test_string == "hello" assert isinstance(t.test_int_to_string, six.text_type) assert t.test_int_to_string == "123" assert isinstance(t.test_float_to_string, six.text_type) assert t.test_float_to_string == "1e-05" assert isinstance(t.test_chinese, six.text_type) assert t.test_chinese == to_text("喵") assert t.test_string_none is None
def encrypt_message(self, reply, timestamp=None, nonce=None): """ 加密微信回复 :param reply: 加密前的回复 :type reply: WeChatReply 或 XML 文本 :return: 加密后的回复文本 """ if hasattr(reply, "render"): reply = reply.render() timestamp = timestamp or to_text(int(time.time())) nonce = nonce or generate_token(5) encrypt = to_text(self.prp_crypto.encrypt(reply, self.app_id)) signature = get_signature(self.token, timestamp, nonce, encrypt) return to_text(self.ENCRYPTED_MESSAGE_XML.format( encrypt=encrypt, signature=signature, timestamp=timestamp, nonce=nonce ))
def create_group(self, name): """ 创建分组 详情请参考 http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 :param name: 分组名字(30个字符以内) :return: 返回的 JSON 数据包 """ name = to_text(name) return self.post(url="https://api.weixin.qq.com/cgi-bin/groups/create", data={"group": {"name": name}})
def parse_user_msg(xml): """ Parse xml from wechat server and return an Message :param xml: raw xml from wechat server. :return: an Message object """ if not xml: return root = ElementTree.fromstring(xml) wechat_message = dict((child.tag, to_text(child.text)) for child in root) locationinfo = root.find('SendLocationInfo') if locationinfo: wechat_message.pop("SendLocationInfo") wechat_message.update( dict((child.tag, to_text(child.text)) for child in locationinfo)) wechat_message["raw"] = xml wechat_message["type"] = wechat_message.pop("MsgType") message_type = MESSAGE_TYPES.get(wechat_message["type"], UnknownMessage) return message_type(wechat_message)
def test_filter(): import re import werobot.testing robot = WeRoBot(enable_session=False) @robot.filter("喵") def _1(): return "喵" assert len(robot._handlers["text"]) == 1 @robot.filter(re.compile(to_text(".*?呵呵.*?"))) def _2(): return "哼" assert len(robot._handlers["text"]) == 2 @robot.text def _3(): return "汪" assert len(robot._handlers["text"]) == 3 tester = werobot.testing.WeTest(robot) assert tester.send_xml(_make_xml("啊"))._args['content'] == u"汪" assert tester.send_xml(_make_xml("啊呵呵"))._args['content'] == u"哼" assert tester.send_xml(_make_xml("喵"))._args['content'] == u"喵" try: os.remove(os.path.abspath("werobot_session")) except OSError: pass robot = WeRoBot(enable_session=False) @robot.filter("帮助", "跪求帮助", re.compile(".*?help.*?")) def _(): return "就不帮" assert len(robot._handlers["text"]) == 3 @robot.text def _4(): return "哦" assert len(robot._handlers["text"]) == 4 tester = werobot.testing.WeTest(robot) assert tester.send_xml(_make_xml("啊"))._args['content'] == u"哦" assert tester.send_xml(_make_xml("帮助"))._args['content'] == u"就不帮" assert tester.send_xml(_make_xml("跪求帮助"))._args['content'] == u"就不帮" assert tester.send_xml(_make_xml("ooohelp"))._args['content'] == u"就不帮"
class VoiceReply(WeChatReply): TEMPLATE = to_text(""" <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[voice]]></MsgType> <Voice> <MediaId><![CDATA[{media_id}]]></MediaId> </Voice> </xml> """)
class TransferCustomerServiceReply(WeChatReply): TEMPLATE = to_text(""" <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[transfer_customer_service]]></MsgType> </xml> """) def render(self): return TransferCustomerServiceReply.TEMPLATE.format(**self._args)
def create_group(self, name): """ 创建分组。 :param name: 分组名字(30个字符以内) :return: 返回的 JSON 数据包 """ name = to_text(name) return self.post( url="https://api.weixin.qq.com/cgi-bin/groups/create", data={"group": {"name": name}} )
def create_group(self, name): """ 创建分组。 :param name: 分组名字(30个字符以内) :return: 返回的 JSON 数据包 """ name = to_text(name) return self.post(url="https://api.weixin.qq.com/cgi-bin/groups/create", data={"group": { "name": name }})
def parse_user_msg(xml): """ Parse xml from wechat server and return an Message :param xml: raw xml from wechat server. :return: an Message object """ if not xml: return root = ElementTree.fromstring(xml) wechat_message = dict((child.tag, to_text(child.text)) for child in root) locationinfo = root.find('SendLocationInfo') if locationinfo: wechat_message.pop("SendLocationInfo") wechat_message.update(dict((child.tag, to_text(child.text)) for child in locationinfo)) wechat_message["raw"] = xml wechat_message["type"] = wechat_message.pop("MsgType") message_type = MESSAGE_TYPES.get(wechat_message["type"], UnknownMessage) return message_type(wechat_message)
def test_article(): article = Article(title="tt", description=to_binary("附近的萨卡里发生"), img="http", url="uuu") assert article.render().strip() == to_text(""" <item> <Title><![CDATA[tt]]></Title> <Description><![CDATA[附近的萨卡里发生]]></Description> <PicUrl><![CDATA[http]]></PicUrl> <Url><![CDATA[uuu]]></Url> </item> """).strip()
def update_group(self, group_id, name): """ 修改分组名 详情请参考 http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 :param group_id: 分组id,由微信分配 :param name: 分组名字(30个字符以内) :return: 返回的 JSON 数据包 """ return self.post( url="https://api.weixin.qq.com/cgi-bin/groups/update", data={"group": {"id": int(group_id), "name": to_text(name)}}, )
def TEMPLATE(self): if 'account' in self._args: return to_text(""" <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[transfer_customer_service]]></MsgType> <TransInfo> <KfAccount><![CDATA[{account}]]></KfAccount> </TransInfo> </xml> """) else: return to_text(""" <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[transfer_customer_service]]></MsgType> </xml> """)
class TextReply(WeChatReply): TEMPLATE = to_text(""" <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[{content}]]></Content> </xml> """) def render(self): return TextReply.TEMPLATE.format(**self._args)
def test_article(): article = Article( title="tt", description=to_binary("附近的萨卡里发生"), img="http", url="uuu" ) assert article.render().strip() == to_text( """ <item> <Title><![CDATA[tt]]></Title> <Description><![CDATA[附近的萨卡里发生]]></Description> <PicUrl><![CDATA[http]]></PicUrl> <Url><![CDATA[uuu]]></Url> </item> """ ).strip()
def update_group(self, group_id, name): """ 修改分组名。 :param group_id: 分组 ID,由微信分配 :param name: 分组名字(30个字符以内) :return: 返回的 JSON 数据包 """ return self.post( url="https://api.weixin.qq.com/cgi-bin/groups/update", data={"group": { "id": int(group_id), "name": to_text(name) }})
def create_group(self, name): """ 创建分组 详情请参考 http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 :param name: 分组名字(30个字符以内) :return: 返回的 JSON 数据包 """ name = to_text(name) return self.post(url="https://api.weixin.qq.com/cgi-bin/groups/create", data={"group": { "name": name }})
class ImageReply(WeChatReply): TEMPLATE = to_text(""" <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[image]]></MsgType> <Image> <MediaId><![CDATA[{media_id}]]></MediaId> </Image> </xml> """) def render(self): return ImageReply.TEMPLATE.format(**self._args)
def update_group(self, group_id, name): """ 修改分组名。 :param group_id: 分组 ID,由微信分配 :param name: 分组名字(30个字符以内) :return: 返回的 JSON 数据包 """ return self.post( url="https://api.weixin.qq.com/cgi-bin/groups/update", data={"group": { "id": int(group_id), "name": to_text(name) }} )
def update_group(self, group_id, name): """ 修改分组名 详情请参考 http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 :param group_id: 分组id,由微信分配 :param name: 分组名字(30个字符以内) :return: 返回的 JSON 数据包 """ return self.post( url="https://api.weixin.qq.com/cgi-bin/groups/update", data={"group": { "id": int(group_id), "name": to_text(name) }})
def parse_user_msg(xml): """ Parse xml from wechat server and return an Message :param xml: raw xml from wechat server. :return: an Message object """ if not xml: return wechat_message = dict((child.tag, to_text(child.text)) for child in ElementTree.fromstring(xml)) wechat_message["raw"] = xml wechat_message["type"] = wechat_message.pop("MsgType").lower() message_type = MESSAGE_TYPES.get(wechat_message["type"], UnknownMessage) return message_type(wechat_message)
def __init__(self, message=None, **kwargs): if message and "source" not in kwargs: kwargs["source"] = message.target if message and "target" not in kwargs: kwargs["target"] = message.source if 'time' not in kwargs: kwargs["time"] = int(time.time()) args = defaultdict(str) for k, v in kwargs.items(): if is_string(v): v = to_text(v) args[k] = v self.process_args(args) self._args = args
def __init__(self, message=None, **kwargs): if "source" not in kwargs and isinstance(message, WeChatMessage): kwargs["source"] = message.target if "target" not in kwargs and isinstance(message, WeChatMessage): kwargs["target"] = message.source if 'time' not in kwargs: kwargs["time"] = int(time.time()) args = dict() for k, v in kwargs.items(): if is_string(v): v = to_text(v) args[k] = v self._args = args
class VideoReply(WeChatReply): TEMPLATE = to_text(""" <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[video]]></MsgType> <Video> <MediaId><![CDATA[{media_id}]]></MediaId> <Title><![CDATA[{title}]]></Title> <Description><![CDATA[{description}]]></Description> </Video> </xml> """) def render(self): return VideoReply.TEMPLATE.format(**self._args)
def test_wechat_reply(): message = parse_user_msg(""" <xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[image]]></MsgType> <PicUrl><![CDATA[this is a url]]></PicUrl> <MediaId><![CDATA[media_id]]></MediaId> <MsgId>1234567890123456</MsgId> </xml> """) s = to_binary("喵fdsjaklfsk") reply = WeChatReply(message=message, s=s) assert reply._args['source'] == 'toUser' assert reply._args['target'] == 'fromUser' assert reply._args['s'] == to_text(s) assert isinstance(reply._args['time'], int)
def filter(self, *args): """ Shortcut for ``text`` messages ``@filter("xxx")``, ``@filter(re.compile("xxx"))`` or ``@filter("xxx", "xxx2")`` to handle message with special content """ content_is_list = False if len(args) > 1: content_is_list = True else: target_content = args[0] if isinstance(target_content, six.string_types): target_content = to_text(target_content) def _check_content(message): return message.content == target_content elif hasattr(target_content, "match") \ and callable(target_content.match): # 正则表达式什么的 def _check_content(message): return target_content.match(message.content) else: raise TypeError( "%s is not a valid target_content" % target_content ) def wraps(f): if content_is_list: for x in args: self.filter(x)(f) return f argc = len(signature(f).parameters.keys()) @self.text def _f(message, session=None): if _check_content(message): return f(*[message, session][:argc]) return f return wraps
def test_message_crypt(): encoding_aes_key = generate_token(32) + generate_token(11) token = generate_token() timestamp = to_text(int(time.time())) nonce = generate_token(5) app_id = generate_token(18) crypt = MessageCrypt( token=token, encoding_aes_key=encoding_aes_key, app_id=app_id ) message = crypt.encrypt_message('hello', timestamp, nonce) assert message is not None message = parse_xml(message) assert message is not None message = crypt.decrypt_message( message['TimeStamp'], message['Nonce'], message['MsgSignature'], message['Encrypt'] ) assert message == to_binary('hello')
def decrypt(self, text, app_id): """ 对密文进行解密 :param text: 需要解密的密文 :param app_id: 微信公众平台的 AppID :return: 解密后的字符串 """ text = to_binary(text) plain_text = self.cipher.decrypt(base64.b64decode(text)) padding = byte2int(plain_text, -1) content = plain_text[16:-padding] xml_len = socket.ntohl(struct.unpack("I", content[:4])[0]) xml_content = content[4:xml_len+4] from_appid = content[xml_len+4:] if to_text(from_appid) != app_id: raise AppIdValidationError(text, app_id) return xml_content
def add_filter(self, func, rules): """ 为 BaseRoBot 添加一个 ``filter handler``。 :param func: 如果 rules 通过,则处理该消息的 handler。 :param rules: 一个 list,包含要匹配的字符串或者正则表达式。 :return: None """ if not callable(func): raise ValueError("{} is not callable".format(func)) if not isinstance(rules, list): raise ValueError("{} is not list".format(rules)) if len(rules) > 1: for x in rules: self.add_filter(func, [x]) else: target_content = rules[0] if isinstance(target_content, six.string_types): target_content = to_text(target_content) def _check_content(message): return message.content == target_content elif is_regex(target_content): def _check_content(message): return target_content.match(message.content) else: raise TypeError("%s is not a valid rule" % target_content) argc = len(signature(func).parameters.keys()) @self.text def _f(message, session=None): _check_result = _check_content(message) if _check_result: if isinstance(_check_result, bool): _check_result = None return func(*[message, session, _check_result][:argc])
def render(self): return to_text(self.TEMPLATE.format(**self._args))
def xml2dict(self, xml): doc = ElementTree.fromstring(xml) return dict((x.tag, to_text(x.text)) for x in doc)
</Video> </xml> """) def process_args(self, args): args.setdefault('title', '') args.setdefault('description', '') Article = renderable_named_tuple( typename="Article", field_names=("title", "description", "img", "url"), tempalte=to_text(""" <item> <Title><![CDATA[{title}]]></Title> <Description><![CDATA[{description}]]></Description> <PicUrl><![CDATA[{img}]]></PicUrl> <Url><![CDATA[{url}]]></Url> </item> """) ) class ArticlesReply(WeChatReply): TEMPLATE = to_text(""" <xml> <ToUserName><![CDATA[{target}]]></ToUserName> <FromUserName><![CDATA[{source}]]></FromUserName> <CreateTime>{time}</CreateTime> <MsgType><![CDATA[news]]></MsgType> <Content><![CDATA[{content}]]></Content> <ArticleCount>{count}</ArticleCount>
def test_filter(): import re import werobot.testing robot = WeRoBot(enable_session=False) @robot.filter("喵") def _1(): return "喵" assert len(robot._handlers["text"]) == 1 @robot.filter(re.compile(to_text(".*?呵呵.*?"))) def _2(): return "哼" assert len(robot._handlers["text"]) == 2 @robot.text def _3(): return "汪" assert len(robot._handlers["text"]) == 3 def _make_xml(content): return """ <xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[%s]]></Content> <MsgId>1234567890123456</MsgId> </xml> """ % content tester = werobot.testing.WeTest(robot) assert tester.send_xml(_make_xml("啊"))._args['content'] == u"汪" assert tester.send_xml(_make_xml("啊呵呵"))._args['content'] == u"哼" assert tester.send_xml(_make_xml("喵"))._args['content'] == u"喵" try: os.remove(os.path.abspath("werobot_session")) except OSError: pass robot = WeRoBot(enable_session=False) @robot.filter("帮助", "跪求帮助", re.compile(".*?help.*?")) def _(): return "就不帮" assert len(robot._handlers["text"]) == 3 @robot.text def _4(): return "哦" assert len(robot._handlers["text"]) == 4 tester = werobot.testing.WeTest(robot) assert tester.send_xml(_make_xml("啊"))._args['content'] == u"哦" assert tester.send_xml(_make_xml("帮助"))._args['content'] == u"就不帮" assert tester.send_xml(_make_xml("跪求帮助"))._args['content'] == u"就不帮" assert tester.send_xml(_make_xml("ooohelp"))._args['content'] == u"就不帮"
def __get__(self, instance, owner): v = get_value(instance, self.entry, self.default) if v is not None: return to_text(v) return v
def render(self): return to_text( self.__TEMPLATE__.format(**self.process_args(self.args)) )