Beispiel #1
0
 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
Beispiel #2
0
class ArticlesReply(WeChatReply):
    TEMPLATE = to_text("""
    <xml>
    <ToUserName><![CDATA[{target}]]></ToUserName>
    <FromUserName><![CDATA[{source}]]></FromUserName>
    <CreateTime>{time}</CreateTime>
    <MsgType><![CDATA[news]]></MsgType>
    <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)
Beispiel #3
0
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>
    """)
Beispiel #4
0
    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.corp_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))
Beispiel #5
0
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>
    """)
Beispiel #6
0
    def update_department(self, department_id, name):
        """
        修改分组名。

        :param department_id: 分组 ID,由微信分配
        :param name: 分组名字(30个字符以内)
        :return: 返回的 JSON 数据包
        """
        return self.post(
            url="https://qyapi.weixin.qq.com/cgi-bin/departments/update",
            data={
                "department": {
                    "id": int(department_id),
                    "name": to_text(name)
                }
            })
Beispiel #7
0
    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
Beispiel #8
0
    def create_department(self, name, parentid, order=None, id=None):
        """
        创建分组。

        :param name: 分组名字(30个字符以内)
        :return: 返回的 JSON 数据包

        """
        name = to_text(name)
        return self.post(
            url="https://qyapi.weixin.qq.com/cgi-bin/departments/create",
            data={
                "name": name,
                "parentid": parentid,
                "order": order,
                "id": id
            })
Beispiel #9
0
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 process_args(self, args):
        args.setdefault('title', '')
        args.setdefault('description', '')
Beispiel #10
0
    def decrypt(self, text, corp_id):
        """
        对密文进行解密
        :param text: 需要解密的密文
        :param corp_id: 微信公众平台的 AppID
        :return: 解密后的字符串
        """
        text = to_binary(text)
        decryptor = self.cipher.decryptor()
        plain_text = decryptor.update(
            base64.b64decode(text)) + decryptor.finalize()

        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) != corp_id:
            raise AppIdValidationError(text, corp_id)

        return xml_content
Beispiel #11
0
    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])
Beispiel #12
0
 def render(self):
     return to_text(self.TEMPLATE.format(**self._args))
Beispiel #13
0
 def render(self):
     return to_text(
         self.__TEMPLATE__.format(**self.process_args(self.args)))
Beispiel #14
0
    </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>
    <ArticleCount>{count}</ArticleCount>
    <Articles>{items}</Articles>
    </xml>
Beispiel #15
0
 def __get__(self, instance, owner):
     v = get_value(instance, self.entry, self.default)
     if v is not None:
         return to_text(v)
     return v