Beispiel #1
0
    async def add_contact_way(self,
                              type,
                              scene,
                              style=None,
                              remark=None,
                              skip_verify=True,
                              state=None,
                              user=None,
                              party=None):
        """
        配置客户联系「联系我」方式
        https://work.weixin.qq.com/api/doc#90000/90135/91559

        :param type: 联系方式类型,1-单人, 2-多人
        :param scene: 场景,1-在小程序中联系,2-通过二维码联系
        :param style: 在小程序中联系时使用的控件样式,详见附表
        :param remark: 联系方式的备注信息,用于助记,不超过30个字符
        :param skip_verify: 外部客户添加时是否无需验证,默认为true
        :param state: 企业自定义的state参数,用于区分不同的添加渠道,在调用“获取外部联系人详情”时会返回该参数值
        :param user: 使用该联系方式的用户userID列表,在type为1时为必填,且只能有一个
        :param party: 使用该联系方式的部门id列表,只在type为2时有效
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(type=type,
                            scene=scene,
                            style=style,
                            remark=remark,
                            skip_verify=skip_verify,
                            state=state,
                            user=user,
                            party=party)
        return await self._post('externalcontact/add_contact_way', data=data)
 def test_init_with_none(self):
     d = optionaldict(
         a=1,
         b=None
     )
     self.assertEqual(1, d['a'])
     self.assertTrue('b' not in d)
Beispiel #3
0
    def _request(self, method, url_or_endpoint, **kwargs):
        if not url_or_endpoint.startswith(("http://", "https://")):
            api_base_url = kwargs.pop("api_base_url", self.API_BASE_URL)
            url = "{base}{endpoint}".format(base=api_base_url, endpoint=url_or_endpoint)
        else:
            url = url_or_endpoint

        if isinstance(kwargs.get("data", ""), dict):
            data = optionaldict(kwargs["data"])
            if "mchid" not in data:
                # F**k Tencent
                data.setdefault("mch_id", self.mch_id)
            data.setdefault("sub_mch_id", self.sub_mch_id)
            data.setdefault("nonce_str", random_string(32))
            sign = calculate_signature(data, self.api_key)
            body = dict_to_xml(data, sign)
            body = body.encode("utf-8")
            kwargs["data"] = body

        # 商户证书
        if self.mch_cert and self.mch_key:
            kwargs["cert"] = (self.mch_cert, self.mch_key)

        res = requests.request(method=method, url=url, **kwargs)
        try:
            res.raise_for_status()
        except requests.RequestException as reqe:
            raise WeChatPayException(return_code=None, client=self, request=reqe.request, response=reqe.response)

        return self._handle_result(res)
Beispiel #4
0
    def create(self, project_id, category_id, content, amount, type,
               note=None, visiable=None, tag_ids=None, involve_members=None):
        """
        新建账目

        详情请参考
        http://docs.teambition.com/wiki/bookkeeping-entry#bookkeeping-entry-create

        :param project_id: 项目 ID
        :param category_id: 账目分类 ID
        :param content: 内容
        :param amount: 金额
        :param type: 类型,1 为收入,-1 为支出
        :param note: 可选,备注
        :param visiable: 可选,可见范围
        :param tag_ids: 可选,标签 ID 列表
        :param involve_members: 可选,参与者 ID 列表
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            _projectId=project_id,
            _entryCategoryId=category_id,
            content=content,
            amount=amount,
            type=type,
            note=note,
            visiable=visiable,
            tagIds=tag_ids,
            involveMembers=involve_members
        )
        return self._post(
            'api/entries',
            data=data
        )
Beispiel #5
0
    def create_version(self, id, file_name, file_size, file_type,
                       file_category, file_key, image_width=None,
                       image_height=None, involve_members=None):
        """
        新建文件

        详情请参考
        http://docs.teambition.com/wiki/works-versions#works-versions-post

        :param id: 文件 ID
        :param file_name: 文件名
        :param file_size: 文件大小
        :param file_type: 文件类型
        :param file_category: 文件类别
        :param file_key: 使用 striker 服务上传后可得
        :param image_width: 可选,图片宽度
        :param image_height: 可选,图片高度
        :param involve_members: 可选
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            fileName=file_name,
            fileSize=file_size,
            fileType=file_type,
            fileCategory=file_category,
            fileKey=file_key,
            imageWidth=image_width,
            imageHeight=image_height,
            involveMembers=involve_members
        )
        return self._post(
            'api/works/{0}/versions'.format(id),
            data=data
        )
Beispiel #6
0
    def update_device(self, device_id=None, uuid=None, major=None,
                      minor=None, comment=None):
        """
        更新设备信息
        详情请参考
        http://mp.weixin.qq.com/wiki/15/b9e012f917e3484b7ed02771156411f3.html

        :param device_id: 设备编号,若填了UUID、major、minor,则可不填设备编号,若二者都填,则以设备编号为优先
        :param uuid: UUID
        :param major: major
        :param minor: minor
        :param comment: 设备的备注信息,不超过15个汉字或30个英文字母。
        :return: 返回的 JSON 数据包
        """
        data = optionaldict()
        data['comment'] = comment
        data['device_identifier'] = {
            'device_id': device_id,
            'uuid': uuid,
            'major': major,
            'minor': minor
        }
        return self._post(
            'shakearound/device/update',
            data=data
        )
Beispiel #7
0
    def update_webhook(self, id, hook_id, callback_url=None, active=True,
                       events=None, add_events=None, remove_events=None):
        """
        更新项目 webhook

        :param id: 项目 ID
        :param hook_id: webhook ID
        :param callback_url: 可选,回调地址,Teambition通过HEAD请求进行测试, 有事件被触发将发送POST请求
        :param active: 可选,是否激活,默认为 True
        :param events: 可选,事件列表,默认为空
        :param add_events: 可选,追加新的事件进去
        :param remove_events: 可选,从原有的事件列表中移除
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            callbackURL=callback_url,
            active=active,
            events=events,
            addEvents=add_events,
            removeEvents=remove_events
        )
        return self._put(
            'api/projects/{0}/hooks/{1}'.format(id, hook_id),
            data=data
        )
Beispiel #8
0
    def get_used_flow(
            self,
            start_date,
            end_date,
    ):
        """
        查询账号一段时间内使用的流量
        查询整体账号一段时间内使用的总流量。 注:流量的统计不是实时的,每天统计一次。

        :param start_date: 查询起始日期,时间格式为yyyy-mm-dd,如:2017-08-01
        :param end_date: 查询结束日期,时间格式为yyyy-mm-dd,如:2017-08-01
        """
        if isinstance(start_date, datetime.date):
            start_date = start_date.strftime('%Y-%m-%d')
        if isinstance(end_date, datetime.date):
            end_date = end_date.strftime('%Y-%m-%d')
        return self._post(
            '/openapi/video_account/getUsedFlow',
            optionaldict({
                'partner_id': self.partner_id,
                'start_date': start_date,
                'end_date': end_date,
            }),
            result_processor=lambda x: x['flow']
        )
Beispiel #9
0
    def process_save(self,
                     name,
                     description,
                     form_component_list=(),
                     process_code=None,
                     agentid=None):
        """
        保存审批模板

        :param name: 模板名称
        :param description: 模板描述
        :param form_component_list: 表单列表
        :param process_code: 模板的唯一码
        :param agentid: 企业微应用标识
        """
        form_component_list = [
            form.get_dict() if isinstance(form, FieldBase) else form
            for form in form_component_list
        ]

        return self._top_request("dingtalk.oapi.process.save", {
            "saveProcessRequest":
            optionaldict({
                "agentid": agentid,
                "process_code": process_code,
                "name": name,
                "description": description,
                "fake_mode": True,
                "form_component_list": form_component_list
            })
        },
                                 result_processor=lambda x: x['process_code'])
Beispiel #10
0
    def invite_user(self, url, token, encoding_aes_key, user_ids=None,
                    party_ids=None, tag_ids=None, invite_tips=None):
        """
        邀请成员关注(deprecated)
        https://qydev.weixin.qq.com/wiki/index.php?title=异步任务接口

        :param url: 企业应用接收企业微信推送请求的访问协议和地址,支持http或https协议
        :param token: 用于生成签名
        :param encoding_aes_key: 用于消息体的加密,是AES密钥的Base64编码
        :param user_ids: 可选,成员ID列表,多个接收者用‘|’分隔,最多支持1000个。
        :param party_ids: 可选,部门ID列表,多个接收者用‘|’分隔,最多支持100个。
        :param tag_ids: 可选,标签ID列表,多个接收者用‘|’分隔。
        :param invite_tips: 可选,推送到微信上的提示语
        :return: 返回的 JSON 数据包
        """
        data = optionaldict()
        data['callback'] = {
            'url': url,
            'token': token,
            'encodingaeskey': encoding_aes_key
        }
        if isinstance(user_ids, (tuple, list)):
            user_ids = '|'.join(map(to_text, user_ids))
        if isinstance(party_ids, (tuple, list)):
            party_ids = '|'.join(map(to_text, party_ids))
        if isinstance(tag_ids, (tuple, list)):
            tag_ids = '|'.join(map(to_text, tag_ids))
        data['touser'] = user_ids
        data['toparty'] = party_ids
        data['totag'] = tag_ids
        data['invite_tips'] = invite_tips
        return self._post('batch/inviteuser', data=data)
Beispiel #11
0
 def get_wxa_code_unlimited(self,
                            scene,
                            width=430,
                            auto_color=False,
                            line_color={
                                "r": "0",
                                "g": "0",
                                "b": "0"
                            },
                            page=None,
                            is_hyaline=False):
     """
     创建小程序码(接口B:适用于需要的码数量极多,或仅临时使用的业务场景)
     详情请参考
     https://mp.weixin.qq.com/debug/wxadoc/dev/api/qrcode.html
     """
     return self._post('wxa/getwxacodeunlimit',
                       data=optionaldict(
                           scene=scene,
                           page=page,
                           width=width,
                           auto_color=auto_color,
                           line_color=line_color,
                           is_hyaline=is_hyaline,
                       ))
Beispiel #12
0
    def update(
        self,
        user_id,
        name=None,
        department=None,
        position=None,
        mobile=None,
        gender=None,
        tel=None,
        email=None,
        weixin_id=None,
        enable=None,
        extattr=None,
        **kwargs,
    ):
        """
        更新成员

        https://work.weixin.qq.com/api/doc#90000/90135/90197
        """
        user_data = optionaldict()
        user_data["userid"] = user_id
        user_data["name"] = name
        user_data["gender"] = gender
        user_data["department"] = department
        user_data["position"] = position
        user_data["mobile"] = mobile
        user_data["tel"] = tel
        user_data["email"] = email
        user_data["weixinid"] = weixin_id
        user_data["extattr"] = extattr
        user_data["enable"] = enable
        user_data.update(kwargs)

        return self._post("user/update", data=user_data)
Beispiel #13
0
    async def update(self,
                     user_id,
                     name=None,
                     department=None,
                     position=None,
                     mobile=None,
                     gender=None,
                     tel=None,
                     email=None,
                     weixin_id=None,
                     enable=None,
                     extattr=None,
                     **kwargs):
        """
        更新成员

        https://work.weixin.qq.com/api/doc#90000/90135/90197
        """
        user_data = optionaldict()
        user_data['userid'] = user_id
        user_data['name'] = name
        user_data['gender'] = gender
        user_data['department'] = department
        user_data['position'] = position
        user_data['mobile'] = mobile
        user_data['tel'] = tel
        user_data['email'] = email
        user_data['weixinid'] = weixin_id
        user_data['extattr'] = extattr
        user_data['enable'] = enable
        user_data.update(kwargs)

        return await self._post('user/update', data=user_data)
Beispiel #14
0
    async def update_contact_way(self,
                                 config_id,
                                 remark,
                                 skip_verify=True,
                                 style=None,
                                 state=None,
                                 user=None,
                                 party=None):
        """
        更新企业已配置的「联系我」方式
        https://work.weixin.qq.com/api/doc#90000/90135/91559

        :param config_id: 企业联系方式的配置id
        :param remark: 联系方式的备注信息,不超过30个字符,将覆盖之前的备注
        :param skip_verify: 外部客户添加时是否无需验证
        :param style: 样式,只针对“在小程序中联系”的配置生效
        :param state: 企业自定义的state参数,用于区分不同的添加渠道,在调用“获取外部联系人详情”时会返回该参数值
        :param user: 使用该联系方式的用户列表,将覆盖原有用户列表
        :param party: 使用该联系方式的部门列表,将覆盖原有部门列表,只在配置的type为2时有效
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(config_id=config_id,
                            remark=remark,
                            skip_verify=skip_verify,
                            style=style,
                            state=state,
                            user=user,
                            party=party)
        return await self._post('externalcontact/update_contact_way',
                                data=data)
Beispiel #15
0
    def update(self,
               chat_id,
               op_user,
               name=None,
               owner=None,
               add_user_list=None,
               del_user_list=None):
        """
        修改会话

        详情请参考
        http://qydev.weixin.qq.com/wiki/index.php?title=企业会话接口说明

        :param chat_id: 会话 ID
        :param op_user: 操作人 userid
        :param name: 会话标题
        :param owner: 管理员userid,必须是该会话userlist的成员之一
        :param add_user_list: 会话新增成员列表,成员用userid来标识
        :param del_user_list: 会话退出成员列表,成员用userid来标识
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            chatid=chat_id,
            op_user=op_user,
            name=name,
            owner=owner,
            add_user_list=add_user_list,
            del_user_list=del_user_list,
        )
        return self._post('chat/update', data=data)
Beispiel #16
0
    def get_group_chat_info(self, chat_id: str) -> dict:
        """
        获取客户群详情

        通过客户群ID,获取详情。包括群名、群成员列表、群成员入群时间、入群方式。
        (客户群是由具有客户群使用权限的成员创建的外部群)

        需注意的是,如果发生群信息变动,会立即收到群变更事件,但是部分信息是异步处理,
        可能需要等一段时间调此接口才能得到最新结果

        详细请查阅企业微信官方文档 `获取客户群详情`_ 章节。

        :param chat_id: 客户群ID
        :return: 响应数据

        .. note::
            **权限说明:**

            - 需要使用 `客户联系secret`_ 或配置到 `可调用应用`_ 列表中的自建应用secret
              来初始化 :py:class:`wechatpy.work.client.WeChatClient` 类。
            - 第三方应用需具有“企业客户权限->客户基础信息”权限
            - 对于第三方/自建应用,群主必须在应用的可见范围。

        .. _获取客户群详情: https://work.weixin.qq.com/api/doc/90000/90135/92122
        """
        data = optionaldict(chat_id=chat_id)
        return self._post("externalcontact/groupchat/get", data=data)
Beispiel #17
0
    def update(self, name=None, avatar_url=None, title=None, birthday=None, location=None, phone=None, website=None):
        """
        更新个人信息

        详情请参考
        http://docs.teambition.com/wiki/me#me-update-info

        :param name: 可选,姓名
        :param avatar_url: 可选,头像地址
        :param title: 可选,职位
        :param birthday: 可选,出生日期
        :param location: 可选,所在地
        :param phone: 可选,手机号码
        :param website: 可选,个人站点
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            name=name,
            avatarUrl=avatar_url,
            title=title,
            birthday=birthday,
            location=location,
            phone=phone,
            website=website,
        )
        return self._put("api/users", data=data)
Beispiel #18
0
    def add_group_welcome_template(self, template: dict, agentid: Optional[int] = None) -> dict:
        """
        添加群欢迎语素材

        企业可通过此API向企业的入群欢迎语素材库中添加素材。每个企业的入群欢迎语素材库中,
        最多容纳100个素材。

        详细请查阅企业微信官方文档 `添加群欢迎语素材`_ 章节。

        :param template: 群欢迎语素材内容,详细字段请参考微信文档
        :param agentid: 授权方安装的应用agentid。仅旧的第三方多应用套件需要填此参数
        :return: 响应数据

        .. note::
            **权限说明:**

            - 需要使用 `客户联系secret`_ 或配置到 `可调用应用`_ 列表中的自建应用secret
              来初始化 :py:class:`wechatpy.work.client.WeChatClient` 类。
            - 第三方应用需具有“企业客户权限->客户联系->配置入群欢迎语素材”权限

        .. _添加群欢迎语素材: https://work.weixin.qq.com/api/doc/90000/90135/
            92366#%E6%B7%BB%E5%8A%A0%E5%85%A5%E7%BE%A4%E6%AC%A2%E8%BF%8E%E
            8%AF%AD%E7%B4%A0%E6%9D%90

        """
        data = optionaldict()
        data.update(template)
        data["agentid"] = agentid
        return self._post("externalcontact/group_welcome_template/add", data=data)
Beispiel #19
0
    def get(self, id=None, team_id=None, is_archived=False):
        """
        获取项目信息

        详情请参考
        http://docs.teambition.com/wiki/projects#projects-get

        :param id: 可选,不提供则返回用户所在的项目
        :param team_id: 可选,团队 ID,提供可获取团队所在项目
        :param is_archived: 返回归档的项目,默认为 False
        :return: 返回的 JSON 数据包
        """
        params = optionaldict(
            _teamId=team_id,
            isArchived=is_archived
        )
        if id is None:
            endpoint = 'api/projects'
        else:
            endpoint = 'api/projects/{0}'.format(id)

        return self._get(
            endpoint,
            params=params
        )
Beispiel #20
0
    def update_group_welcome_template(self, template: dict, template_id: str, agentid: Optional[int] = None) -> dict:
        """
        编辑群欢迎语素材

        企业可通过此API编辑入群欢迎语素材库中的素材,且仅能够编辑调用方自己创建的入群欢迎语素材。


        详细请查阅企业微信官方文档 `编辑群欢迎语素材`_ 章节。

        :param template: 群欢迎语素材内容,详细字段请参考微信文档
        :param template_id: 欢迎语素材id
        :param agentid: 授权方安装的应用agentid。仅旧的第三方多应用套件需要填此参数
        :return: 响应数据

        .. note::
            **权限说明:**

            - 需要使用 `客户联系secret`_ 或配置到 `可调用应用`_ 列表中的自建应用secret
              来初始化 :py:class:`wechatpy.work.client.WeChatClient` 类。
            - 第三方应用需具有“企业客户权限->客户联系->配置入群欢迎语素材”权限
            - 仅可编辑本应用创建的入群欢迎语素材

        .. _添编辑群欢迎语素材: https://work.weixin.qq.com/api/doc/90000/90135/
            92366#%E7%BC%96%E8%BE%91%E5%85%A5%E7%BE%A4%E6%AC%A2%E8%BF%8E%E8%
            AF%AD%E7%B4%A0%E6%9D%90
        """
        data = optionaldict()
        data.update(template)
        data["template_id"] = template_id
        data["agentid"] = agentid
        return self._post("externalcontact/group_welcome_template/edit", data=data)
Beispiel #21
0
    def create(self, title, project_id, parent_id=None, description=None,
               color=None):
        """
        新建文件集

        详情请参考
        http://docs.teambition.com/wiki/collections#collections-create

        :param title: 文件集标题
        :param project_id: 项目 ID
        :param parent_id: 可选,父级 ID,默认为项目 ID
        :param description: 可选,描述
        :param color: 可选,颜色,默认为空
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            title=title,
            _projectId=project_id,
            _parentId=parent_id or project_id,
            description=description,
            color=color
        )
        return self._post(
            'api/collections',
            data=data
        )
Beispiel #22
0
    def del_group_welcome_template(self, template_id: str, agentid: Optional[int] = None) -> dict:
        """
        删除入群欢迎语素材

        企业可通过此API删除入群欢迎语素材,且仅能删除调用方自己创建的入群欢迎语素材。

        详细请查阅企业微信官方文档 `删除入群欢迎语素材`_ 章节。

        :param template_id: 群欢迎语的素材id
        :param agentid: 授权方安装的应用agentid。仅旧的第三方多应用套件需要填此参数
        :return: 响应数据

        .. note::
            **权限说明:**

            - 需要使用 `客户联系secret`_ 或配置到 `可调用应用`_ 列表中的自建应用secret
              来初始化 :py:class:`wechatpy.work.client.WeChatClient` 类。
            - 第三方应用需具有“企业客户权限->客户联系->配置入群欢迎语素材”权限
            - 仅可删除本应用创建的入群欢迎语素材

        .. _删除入群欢迎语素材: https://work.weixin.qq.com/api/doc/90000/90135/
            92366#%E5%88%A0%E9%99%A4%E5%85%A5%E7%BE%A4%E6%AC%A2%E8%BF%8E%E8
            %AF%AD%E7%B4%A0%E6%9D%90
        """
        data = optionaldict(template_id=template_id, agentid=agentid)
        return self._post("externalcontact/group_welcome_template/del", data=data)
Beispiel #23
0
    def create(self, content, tasklist_id, stage_id=None, executor_id=None,
               involve_members=None, due_date=None, priority=None,
               recurrence=None, tag_ids=None):
        """
        创建任务

        详情请参考
        http://docs.teambition.com/wiki/tasks#tasks-create

        :param content: 任务内容
        :param tasklist_id: 任务分组 ID
        :param stage_id: 可选,阶段 ID,默认为任务分组的第一个阶段
        :param executor_id: 可选,执行者 ID,默认为空
        :param involve_members: 可选,参与者 ID 数组,默认为创建者和执行者
        :param due_date: 可选,截止日期
        :param priority: 可选,优先级,可选值为 0,1,2,对应普通、紧急、非常紧急
        :param recurrence: 可选,重复规则列表
        :param tag_ids: 可选,标签 ID 列表
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            content=content,
            _tasklistId=tasklist_id,
            _stageId=stage_id,
            _executorId=executor_id,
            involveMembers=involve_members,
            dueDate=due_date,
            priority=priority,
            recurrence=recurrence,
            tagIds=tag_ids
        )
        return self._post(
            'api/tasks',
            data=data
        )
Beispiel #24
0
    def del_contact_way(self, config_id: str) -> dict:
        """
        删除企业已配置的「联系我」方式

        删除一个已配置的「联系我」二维码或者「联系我」小程序按钮。

        详细请查阅企业微信官方文档 `删除企业已配置的「联系我」方式`_ 章节。

        :param config_id: 企业联系方式的配置id
        :return: 返回的 JSON 数据包

        .. note::
            **调用接口应满足如下的权限要求:**

            - 需要使用 `客户联系secret`_ 或配置到 `可调用应用`_ 列表中的自建应用secret
              来初始化 :py:class:`wechatpy.work.client.WeChatClient` 类。
            - 使用人员需要配置了 `客户联系功能`_。
            - 第三方调用时,应用需具有 `企业客户权限`_。
            - 第三方/自建应用调用时,传入的userid和partyid需要在此应用的可见范围内。
            - 配置的使用成员必须在企业微信激活且已经过实名认证。
            - 临时会话的二维码具有有效期,添加企业成员后仅能在指定有效期内进行会话,
              仅支持医疗行业企业创建。
              临时会话模式可以配置会话结束时自动发送给用户的结束语。

        .. _删除企业已配置的「联系我」方式: https://work.weixin.qq.com/api/doc/90000
           /90135/92572#%E5%88%A0%E9%99%A4%E4%BC%81%E4%B8%9A%E5%B7%B2%E9%85%8D
           %E7%BD%AE%E7%9A%84%E3%80%8C%E8%81%94%E7%B3%BB%E6%88%91%E3%80%8D%E6%
           96%B9%E5%BC%8F

        """
        data = optionaldict(config_id=config_id)
        return self._post("externalcontact/del_contact_way", data=data)
Beispiel #25
0
    def get(self, id=None, parent_id=None, page=None, count=None, all=None):
        """
        获取文件信息

        详情请参考
        http://docs.teambition.com/wiki/works#works-get

        :param id: 可选,文件 ID
        :param parent_id: 可选,父级 ID
        :param page: 可选,当前页,默认为 1
        :param count: 可选,每页数量,默认为 30
        :param all: 可选,若提供此参数则返回所有
        :return: 返回的 JSON 数据包
        """
        assert id or parent_id

        params = optionaldict(
            page=page,
            count=count,
            all=all
        )
        if id:
            endpoint = 'api/works/{0}'.format(id)
        elif parent_id:
            endpoint = 'api/works'
            params['_parentId'] = parent_id
        return self._get(endpoint, params=params)
Beispiel #26
0
    def get_unassigned_list(self, page_id: int = 0, page_size: int = 1000, cursor: Optional[str] = None) -> dict:
        """
        获取离职成员列表

        企业和第三方可通过此接口,获取所有离职成员的客户列表,并可进一步调用
        `分配在职或离职成员的客户`_ 接口将这些客户重新分配给其他企业成员。

        详细请查阅企业微信官方文档 `获取离职成员列表`_ 章节。

        :param page_id: 分页查询,要查询页号,从0开始
        :param page_size: 每次返回的最大记录数,默认为1000,最大值为1000
        :param cursor: 分页查询游标,字符串类型,适用于数据量较大的情况,如果使用该参数
           则无需填写page_id,该参数由上一次调用返回
        :return: 响应结果

        .. note::
           当 ``page_id`` 为1,``page_size`` 为100时,表示取第101到第200条记录。
           由于每个成员的客户数不超过5万,故 ``page_id * page_size`` 必须小于5万。

        .. note::
            **权限说明:**

            - 需要使用 `客户联系secret`_ 或配置到 `可调用应用`_ 列表中的自建应用secret
              来初始化 :py:class:`wechatpy.work.client.WeChatClient` 类。
            - 第三方应用需拥有“企业客户权限->客户联系->分配在职或离职成员的客户”权限

        .. _获取离职成员列表: https://work.weixin.qq.com/api/doc/90000/90135/92124
        """
        data = optionaldict(page_id=page_id, page_size=page_size, cursor=cursor)
        return self._post("externalcontact/get_unassigned_list", data=data)
Beispiel #27
0
    def get_by_filter(self, status=None, begin_time=None, end_time=None):
        filter_dict = optionaldict(status=status, begintime=begin_time, endtime=end_time)

        res = self._post(
            "merchant/order/getbyfilter", data=dict(filter_dict), result_processor=lambda x: x["order_list"]
        )
        return res
Beispiel #28
0
    def set(
        self,
        agent_id,
        name=None,
        description=None,
        redirect_domain=None,
        logo_media_id=None,
        report_location_flag=0,
        is_report_user=True,
        is_report_enter=True,
    ):
        """
        设置应用
        https://work.weixin.qq.com/api/doc#90000/90135/90228

        :param agent_id: 企业应用的id
        :param name: 企业应用名称,长度不超过32个utf8字符
        :param description: 企业应用详情,长度为4至120个utf8字符
        :param redirect_domain: 企业应用可信域名。注意:域名需通过所有权校验,否则jssdk功能将受限,此时返回错误码85005
        :param logo_media_id: 企业应用头像的mediaid,通过素材管理接口上传图片获得mediaid,上传后会自动裁剪成方形和圆形两个头像
        :param report_location_flag: 企业应用是否打开地理位置上报 0:不上报;1:进入会话上报;
        :param is_report_enter: 是否上报用户进入应用事件。0:不接收;1:接收。
        :param is_report_user: 是否接收用户变更通知。0:不接收;1:接收。
        :return: 返回的 JSON 数据包
        """
        agent_data = optionaldict()
        agent_data["agentid"] = agent_id
        agent_data["name"] = name
        agent_data["description"] = description
        agent_data["redirect_domain"] = redirect_domain
        agent_data["logo_mediaid"] = logo_media_id
        agent_data["report_location_flag"] = report_location_flag
        agent_data["isreportenter"] = 1 if is_report_enter else 0
        agent_data["isreportuser"] = 1 if is_report_user else 0
        return self._post("agent/set", data=agent_data)
Beispiel #29
0
    def create(self, project_id, title, content, post_mode=None,
               visiable='members', involve_members=None,
               tag_ids=None, attachments=None):
        """
        新建分享

        详情请参考
        http://docs.teambition.com/wiki/posts#posts-create

        :param project_id: 项目 ID
        :param title: 标题
        :param content: 内容
        :param post_mode: 可选,分享模式
        :param visiable: 可选,可见范围,默认为 members,可选 involves
        :param involve_members: 可选,参与者 ID 列表
        :param tag_ids: 可选,标签 ID 列表
        :param attachments: 可选,附件 ID 列表
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            _projectId=project_id,
            title=title,
            content=content,
            postMode=post_mode,
            visiable=visiable,
            involveMembers=involve_members,
            tagIds=tag_ids,
            attachments=attachments
        )
        return self._post(
            'api/posts',
            data=data
        )
Beispiel #30
0
    def _request(self, method, url_or_endpoint, **kwargs):
        if not url_or_endpoint.startswith('https://'):
            api_base_url = kwargs["data"].pop('api_base_url', self._api_base_url)
            url = f"{api_base_url}{url_or_endpoint}"
        else:
            url = url_or_endpoint
        data = optionaldict(kwargs['data'])
        data.setdefault('mch_id', self._mch_id)
        data.setdefault('appid', self._appid)
        data.setdefault('nonce_str', self._nonce_str or random_string(32))
        data.setdefault("notify_url", self._notify_url)
        sign = calculate_signature(data, self._api_key)
        body = dict_to_xml(data, sign)
        body = body.encode('utf-8')
        kwargs['data'] = body

        # 商户证书
        kwargs['cert'] = (self._apiclient_cert_path, self._apiclient_key_path)

        res = requests.request(
            method=method,
            url=url,
            **kwargs
        )
        try:
            res.raise_for_status()
        except requests.RequestException as reqe:
            raise reqe

        return self._handle_result(res)
Beispiel #31
0
    def get_day_peak_user(
            self,
            start_date,
            end_date,
            product_type=0,
    ):
        """
        查询账号一段时间内每天的最高并发量
        该接口用于获取账号一段时间内每天的最高并发量

        :param start_date: 查询起始日期,格式如:2017-12-12
        :param end_date: 查询结束日期,格式如:2017-12-28
        :param product_type: 1:教育直播 2:小班课 4:企业直播
        """
        if isinstance(start_date, datetime.date):
            start_date = start_date.strftime('%Y-%m-%d')
        if isinstance(end_date, datetime.date):
            end_date = end_date.strftime('%Y-%m-%d')
        return self._post(
            '/openapi/live_account/getDayPeakUser',
            optionaldict({
                'partner_id': self.partner_id,
                'product_type': product_type,
                'start_date': start_date,
                'end_date': end_date,
            }),
            result_processor=lambda x: x['peak_user']
        )
Beispiel #32
0
    def get_url_scheme(self,
                       is_expire=False,
                       expire_type=0,
                       expire_time=None,
                       expire_interval=None,
                       jump_wxa=()):
        """
        获取小程序 scheme 码,适用于短信、邮件、外部网页、微信内等拉起小程序的业务场景。
        详情请参考
        https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.generate.html
        :param is_expire, 到期失效:True,永久有效:False 默认False, 永久有效上限10万
        :params expire_type, 失效时间:0,失效间隔天数:1
        :params expire_time, 到期失效的 scheme 码的失效时间, Unix 时间戳, is_expire 为 true 且 expire_type 为 0 时必填
        :params expire_interval, 到期失效的 scheme 码的失效间隔天数。生成的到期失效 scheme 码在该间隔时间到达前有效。
        最长间隔天数为365天。is_expire 为 true 且 expire_type 为 1 时必填
        :params jump_wxa, 跳转到的目标小程序信息。

        :rtype: requests.Response
        """
        return self._post(
            "wxa/generatescheme",
            data=optionaldict(
                jump_wxa=jump_wxa,
                ie_expire=is_expire,
                expire_type=expire_type,
                expire_time=expire_time,
                expire_interval=expire_interval,
            ),
        )
Beispiel #33
0
    def update(self, chat_id, op_user, name=None, owner=None,
               add_user_list=None, del_user_list=None):
        """
        修改会话

        详情请参考
        http://qydev.weixin.qq.com/wiki/index.php?title=企业会话接口说明

        :param chat_id: 会话 ID
        :param op_user: 操作人 userid
        :param name: 会话标题
        :param owner: 管理员userid,必须是该会话userlist的成员之一
        :param add_user_list: 会话新增成员列表,成员用userid来标识
        :param del_user_list: 会话退出成员列表,成员用userid来标识
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            chatid=chat_id,
            op_user=op_user,
            name=name,
            owner=owner,
            add_user_list=add_user_list,
            del_user_list=del_user_list,
        )
        return self._post('chat/update', data=data)
Beispiel #34
0
 def get_wxa_code_unlimited(
     self,
     scene,
     width=430,
     auto_color=False,
     line_color=None,
     page=None,
     is_hyaline=False,
 ):
     """
     创建小程序码(接口B:适用于需要的码数量极多,或仅临时使用的业务场景)
     详情请参考
     https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html
     """
     if line_color is None:
         line_color = {"r": "0", "g": "0", "b": "0"}
     return self._post(
         "wxa/getwxacodeunlimit",
         data=optionaldict(
             scene=scene,
             page=page,
             width=width,
             auto_color=auto_color,
             line_color=line_color,
             is_hyaline=is_hyaline,
         ),
     )
Beispiel #35
0
    def update_page(self, page_id, title, description,
                    icon_url, page_url, comment=None):
        """
        编辑页面信息
        详情请参考
        http://mp.weixin.qq.com/wiki/5/6626199ea8757c752046d8e46cf13251.html

        :param page_id: 摇周边页面唯一ID
        :param title: 在摇一摇页面展示的主标题,不超过6个字
        :param description: 在摇一摇页面展示的副标题,不超过7个字
        :param icon_url: 在摇一摇页面展示的图片。图片需先上传至微信侧服务器,
                        用“素材管理-上传图片素材”接口上传图片,返回的图片URL再配置在此处
        :param page_url: 跳转链接
        :param comment: 可选,页面的备注信息,不超过15个字
        :return: 页面信息
        """
        data = optionaldict()
        data['page_id'] = page_id
        data['title'] = title
        data['description'] = description
        data['icon_url'] = icon_url
        data['page_url'] = page_url
        data['comment'] = comment
        res = self._post(
            'shakearound/page/update',
            data=data
        )
        return res['data']
Beispiel #36
0
 def send_template_message(
     self,
     user_id,
     template_id,
     data,
     form_id,
     page=None,
     color=None,
     emphasis_keyword=None,
 ):
     """
     ⚠️已废弃
     发送模板消息
     详情请参考
     https://mp.weixin.qq.com/debug/wxadoc/dev/api/notice.html
     """
     tpl_data = optionaldict(
         touser=user_id,
         template_id=template_id,
         page=page,
         form_id=form_id,
         data=data,
         color=color,
         emphasis_keyword=emphasis_keyword,
     )
     return self._post("cgi-bin/message/wxopen/template/send",
                       data=tpl_data)
Beispiel #37
0
    def bind_device_location(self, poi_id, device_id=None, uuid=None,
                             major=None, minor=None):
        """
        配置设备与门店的关联关系
        详情请参考
        http://mp.weixin.qq.com/wiki/15/b9e012f917e3484b7ed02771156411f3.html

        :param poi_id: 待关联的门店ID
        :param device_id: 设备编号,若填了UUID、major、minor,则可不填设备编号,若二者都填,则以设备编号为优先
        :param uuid: UUID
        :param major: major
        :param minor: minor
        :return: 返回的 JSON 数据包
        """
        data = optionaldict()
        data['poi_id'] = poi_id
        data['device_identifier'] = {
            'device_id': device_id,
            'uuid': uuid,
            'major': major,
            'minor': minor
        }
        return self._post(
            'shakearound/device/bindlocation',
            data=data
        )
Beispiel #38
0
    def create(self, name, description=None, logo=None,
               location=None, website=None):
        """
        创建新组织

        详情请参考
        http://docs.teambition.com/wiki/orgs#orgs-create

        :param name: 组织名字
        :param description: 可选,描述
        :param logo: 可选,组织 logo
        :param location: 可选,组织所在地
        :param website: 可选,组织网站
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            name=name,
            description=description,
            logo=logo,
            location=location,
            website=website
        )
        return self._post(
            'api/organizations',
            data=data
        )
Beispiel #39
0
    def create(self, name, description=None, logo=None, categroy=None,
               divider_index=None, organization_id=None):
        """
        新建项目

        详情请参考
        http://docs.teambition.com/wiki/projects#projects-create

        :param name: 项目名称
        :param description: 可选,项目描述
        :param logo: 可选,项目 logo
        :param category: 可选,项目类别
        :param divider_index: 可选,dividers 中得 index,仅对拥有者有效
        :param organization_id: 可选,组织 ID,创建组织项目时需要提供此参数
        :return: 新建的项目信息
        """
        data = optionaldict(
            name=name,
            description=description,
            logo=logo,
            category=categroy,
            dividerIndex=divider_index,
            _organizationId=organization_id
        )
        return self._post(
            'api/projects',
            data=data
        )
Beispiel #40
0
    def get_member_tasks(self, id, member_id, start_date=None, is_done=None,
                         all=False, page=1, count=30):
        """
        获取组织成员任务

        详情请参考
        http://docs.teambition.com/wiki/orgs#orgs-get-member-tasks

        :param id: 组织 ID
        :param member_id: 成员 ID
        :param start_date: 可选,起始日期,默认为当周的起始日期
        :param is_done: 可选,是否完成,默认为 False
        :param all: 可选,是否返回所有
        :param page:  可选,页码
        :param count: 可选,每页数量,默认为 30
        :return: 返回的 JSON 数据包
        """
        params = optionaldict(
            startDate=start_date,
            isDone=is_done,
            all=all,
            page=page,
            count=count
        )
        return self._get(
            'api/organizations/{0}/members/{1}/tasks'.format(id, member_id),
            params=params
        )
Beispiel #41
0
    def update(self, id, name=None, description=None, logo=None,
               category=None, is_archived=None, is_public=None):
        """
        更新项目

        详情请参考
        http://docs.teambition.com/wiki/projects#projects-update

        :param id: 路径参数
        :param name: 项目名称
        :param description: 可选,项目描述
        :param logo: 可选,项目 logo
        :param category: 可选,项目类别
        :param is_archived: 可选,是否归档
        :param is_public: 是否公开,需要拥有者权限
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            name=name,
            description=description,
            logo=logo,
            category=category,
            isArchived=is_archived,
            isPublic=is_public
        )
        return self._put(
            'api/projects/{0}'.format(id),
            data=data
        )
Beispiel #42
0
    def update(self, id, name=None, description=None, logo=None,
               location=None, website=None):
        """
        更新组织信息

        详情请参考
        http://docs.teambition.com/wiki/orgs#orgs-update

        :param id: 组织 ID
        :param name: 组织名字
        :param description: 可选,描述
        :param logo: 可选,组织 logo
        :param location: 可选,组织所在地
        :param website: 可选,组织网站
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            name=name,
            description=description,
            logo=logo,
            location=location,
            website=website
        )
        return self._put(
            'api/organizations/{0}'.format(id),
            data=data
        )
Beispiel #43
0
    def update(self, id, title=None, parent_id=None, description=None,
               color=None):
        """
        更新文件集

        详情请参考
        http://docs.teambition.com/wiki/collections#collections-update

        :param id: 文件集 ID
        :param title: 可选,文件集标题
        :param parent_id: 可选,父级 ID
        :param description: 可选,描述
        :param color: 可选,颜色,默认为空
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            title=title,
            _parentId=parent_id,
            description=description,
            color=color,
            isArchived=is_archived
        )
        return self._put(
            'api/collections/{0}'.format(id),
            data=data
        )
Beispiel #44
0
    def create(self,
               title,
               project_id,
               parent_id=None,
               description=None,
               color=None):
        """
        新建文件集

        详情请参考
        http://docs.teambition.com/wiki/collections#collections-create

        :param title: 文件集标题
        :param project_id: 项目 ID
        :param parent_id: 可选,父级 ID,默认为项目 ID
        :param description: 可选,描述
        :param color: 可选,颜色,默认为空
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(title=title,
                            _projectId=project_id,
                            _parentId=parent_id or project_id,
                            description=description,
                            color=color)
        return self._post('api/collections', data=data)
Beispiel #45
0
    def send_template(self, user_id, template_id, data, url=None, mini_program=None):
        """
        发送模板消息

        详情请参考
        https://mp.weixin.qq.com/wiki?id=mp1445241432&lang=zh_CN

        :param user_id: 用户 ID 。 就是你收到的 `Message` 的 source
        :param template_id: 模板 ID。在公众平台线上模板库中选用模板获得
        :param url: 链接地址
        :param data: 模板消息数据
        :param mini_program: 跳小程序所需数据, 如:`{'appid': 'appid', 'pagepath': 'index?foo=bar'}`
        :return: 返回的 JSON 数据包
        """
        tpl_data = optionaldict(
            touser=user_id,
            template_id=template_id,
            url=url,
            miniprogram=mini_program,
            data=data,
        )
        return self._post(
            'message/template/send',
            data=tpl_data
        )
Beispiel #46
0
    def update(self,
               id,
               title=None,
               parent_id=None,
               description=None,
               color=None):
        """
        更新文件集

        详情请参考
        http://docs.teambition.com/wiki/collections#collections-update

        :param id: 文件集 ID
        :param title: 可选,文件集标题
        :param parent_id: 可选,父级 ID
        :param description: 可选,描述
        :param color: 可选,颜色,默认为空
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(title=title,
                            _parentId=parent_id,
                            description=description,
                            color=color,
                            isArchived=is_archived)
        return self._put('api/collections/{0}'.format(id), data=data)
Beispiel #47
0
    def import_tasks(self, tasklist_id, tasks, stage_id=None, executor_id=None,
                     involve_members=None, due_date=None, visiable=None):
        """
        批量导入任务

        一次允许50条, 仅支持任务标题列表

        :param tasklist_id: 任务分组 ID
        :param tasks: 任务内容列表
        :param stage_id: 可选,阶段 ID,默认分组的第一个阶段
        :param executor_id: 可选,执行者 ID
        :param involve_members: 可选,参与者列表
        :param due_date: 可选,截止日期
        :param visiable: 可选,可见状态
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            tasks=tasks,
            _stageId=stage_id,
            _executorId=executor_id,
            involveMembers=involve_members,
            dueDate=due_date,
            visiable=visiable,
        )
        return self._post(
            'api/tasklists/{0}/import_tasks'.format(tasklist_id),
            data=data
        )
Beispiel #48
0
    def create(self, chat_id=None, name=None, owner=None, user_list=None):
        """
        创建群聊会话

        详情请参考
        https://work.weixin.qq.com/api/doc#90000/90135/90245

        限制说明:
        只允许企业自建应用调用,且应用的可见范围必须是根部门;
        群成员人数不可超过管理端配置的“群成员人数上限”,且最大不可超过500人;
        每企业创建群数不可超过1000/天;

        :param chat_id: 群聊的唯一标志,不能与已有的群重复;字符串类型,最长32个字符。只允许字符0-9及字母a-zA-Z。如果不填,系统会随机生成群id
        :param name: 群聊名,最多50个utf8字符,超过将截断
        :param owner: 指定群主的id。如果不指定,系统会随机从userlist中选一人作为群主
        :param user_list: 会话成员列表,成员用userid来标识。至少2人,至多500人
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            chatid=chat_id,
            name=name,
            owner=owner,
            userlist=user_list,
        )
        return self._post("appchat/create", data=data)
Beispiel #49
0
    def create(self, parent_id, file_name, file_size, file_type, file_category,
               file_key, image_width=None, image_height=None,
               involve_members=None):
        """
        新建文件

        详情请参考
        http://docs.teambition.com/wiki/works#works-create

        :param parent_id: 所属目录 ID
        :param file_name: 文件名
        :param file_size: 文件大小
        :param file_type: 文件类型
        :param file_category: 文件类别
        :param file_key: 使用 striker 服务上传后可得
        :param image_width: 可选,图片宽度
        :param image_height: 可选,图片高度
        :param involve_members: 可选
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            _parentId=parent_id,
            fileName=file_name,
            fileSize=file_size,
            fileType=file_type,
            fileCategory=file_category,
            fileKey=file_key,
            imageWidth=image_width,
            imageHeight=image_height,
            involveMembers=involve_members
        )
        return self._post(
            'api/works',
            data=data
        )
Beispiel #50
0
    def update(self,
               chat_id,
               name=None,
               owner=None,
               add_user_list=None,
               del_user_list=None):
        """
        修改群聊会话

        详情请参考
        https://work.weixin.qq.com/api/doc#90000/90135/90246

        :param chat_id: 群聊id
        :param name: 新的群聊名。若不需更新,请忽略此参数。最多50个utf8字符,超过将截断
        :param owner: 新群主的id。若不需更新,请忽略此参数
        :param add_user_list: 会话新增成员列表,成员用userid来标识
        :param del_user_list: 会话退出成员列表,成员用userid来标识
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            chatid=chat_id,
            name=name,
            owner=owner,
            add_user_list=add_user_list,
            del_user_list=del_user_list,
        )
        return self._post("appchat/update", data=data)
Beispiel #51
0
    def create(self, content, object_id, object_type,
               attachments=None, mentions=None):
        """
        新建动态

        详情请参考
        http://docs.teambition.com/wiki/activities#activities-comment

        :param content: 内容
        :param object_id: 所属对象 ID
        :param object_type: 所属对象类型,目前仅支持评论: post/task/event/entry/work
        :param attachments: 可选,附件 ID 列表
        :param mentions: 可选,提及,格式为 {"user id": "@username"}
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            content=content,
            _boundToObjectId=object_id,
            boundToObjectType=object_type,
            attachments=attachments,
            mentions=mentions
        )
        return self._post(
            'api/activities',
            data=data
        )
Beispiel #52
0
    def get_login_linked(
            self,
            uid,
            class_id,
            course_id,
            life_time=86400,
            device_type=1
    ):
        """
        获取唤醒客户端并进入教室链接
        https://docs.eeo.cn/api/zh-hans/getLoginLinked.html

        :param uid: 用户 UID
        :param class_id: 课节 ID
        :param course_id: 课程 ID
        :param life_time: 密钥有效时长(单位:秒)
        :param device_type: 1代表 Windows/Mac OS 端;2代表 iOS 移动端;3代表 Android
        """
        return self._post(
            params={'action': 'getLoginLinked'},
            data=optionaldict({
                'uid': uid,
                'lifeTime': life_time,
                'courseId': course_id,
                'classId': class_id,
                'deviceType': device_type,
            }),
        )
 def test_pickle_loads(self):
     d = optionaldict(
         a=1,
         b=None
     )
     s = pickle.dumps(d)
     pickle.loads(s)
Beispiel #54
0
    def send_template(self,
                      user_id,
                      template_id,
                      data,
                      url=None,
                      mini_program=None):
        """
        发送模板消息

        详情请参考
        https://mp.weixin.qq.com/wiki?id=mp1445241432&lang=zh_CN

        :param user_id: 用户 ID 。 就是你收到的 `Message` 的 source
        :param template_id: 模板 ID。在公众平台线上模板库中选用模板获得
        :param url: 链接地址
        :param data: 模板消息数据
        :param mini_program: 跳小程序所需数据, 如:`{'appid': 'appid', 'pagepath': 'index?foo=bar'}`
        :return: 返回的 JSON 数据包
        """
        tpl_data = optionaldict(
            touser=user_id,
            template_id=template_id,
            url=url,
            miniprogram=mini_program,
            data=data,
        )
        return self._post('message/template/send', data=tpl_data)
Beispiel #55
0
    def update(self, id, title=None, start_date=None, end_date=None,
               location=None, status=None, reminders=None, content=None):
        """
        更新日程

        详情请参考
        http://docs.teambition.com/wiki/events#events-update

        :param id: 日程 ID
        :param title: 内容
        :param start_date: 开始时间
        :param end_date: 结束时间
        :param location: 可选,地点
        :param status: 可选,状态
        :param reminders: 可选,提醒
        :param content: 可选,备注
        """
        data = optionaldict(
            title=title,
            startDate=start_date,
            endDate=end_date,
            location=location,
            status=status,
            reminders=reminders,
            content=content
        )
        return self._put(
            'api/events/{0}'.format(id),
            data=data
        )
Beispiel #56
0
    def _request(self, method, url_or_endpoint, **kwargs):
        if not url_or_endpoint.startswith(('http://', 'https://')):
            api_base_url = kwargs.pop('api_base_url', self.API_BASE_URL)
            url = '{base}{endpoint}'.format(base=api_base_url,
                                            endpoint=url_or_endpoint)
        else:
            url = url_or_endpoint

        if isinstance(kwargs.get('data', ''), dict):
            data = optionaldict(kwargs['data'])
            if 'mchid' not in data:
                # F**k Tencent
                data.setdefault('mch_id', self.mch_id)
            data.setdefault('sub_mch_id', self.sub_mch_id)
            data.setdefault('nonce_str', random_string(32))
            sign = calculate_signature(data, self.api_key)
            body = dict_to_xml(data, sign)
            body = body.encode('utf-8')
            kwargs['data'] = body

        # 商户证书
        if self.mch_cert and self.mch_key:
            kwargs['cert'] = (self.mch_cert, self.mch_key)

        res = self._http.request(method=method, url=url, **kwargs)
        try:
            res.raise_for_status()
        except requests.RequestException as reqe:
            raise WeChatPayException(return_code=None,
                                     client=self,
                                     request=reqe.request,
                                     response=reqe.response)

        return self._handle_result(res)
Beispiel #57
0
    def get_tasks(self, id, executor_id=None, is_done=False, all=False,
                  page=1, limit=30, **kwargs):
        """
        获取阶段下得任务列表

        详情请参考
        http://docs.teambition.com/wiki/stages#stages-get-tasks

        :param id: 阶段 ID
        :param executor_id: 可选,执行者 ID
        :param is_done: 可选,是否已完成,默认为 False
        :param all: 可选,所有类型,包括完成与未完成
        :param page: 可选,页码,默认为 1
        :param limit: 可选,每页数量,默认为 30,最大值为 1000
        :return: 返回的 JSON 数据包
        """
        params = optionaldict(
            isDone=is_done,
            _executorId=executor_id,
            all=all,
            page=page,
            limit=limit,
            **kwargs
        )
        return self._get(
            'api/stages/{0}/tasks'.format(id),
            params=params
        )
Beispiel #58
0
    def get_partner_daily_cost(
            self,
            start_date,
            end_date,
            product_type=0,
    ):
        """
        查询直播账号每天使用的人次
        该接口用于获取按人次/时长计费的账号,每天消耗的人次

        :param start_date: 开始日期,格式如:2018-02-01
        :param end_date: 结束日期,格式如:2018-02-15
        :param product_type: 1:教育直播 4:企业直播
        """
        if isinstance(start_date, datetime.date):
            start_date = start_date.strftime('%Y-%m-%d')
        if isinstance(end_date, datetime.date):
            end_date = end_date.strftime('%Y-%m-%d')
        return self._post(
            '/openapi/live_account/getPartnerDailyCost',
            optionaldict({
                'partner_id': self.partner_id,
                'product_type': product_type,
                'start_date': start_date,
                'end_date': end_date,
            }),
            result_processor=lambda x: x['cost']
        )
Beispiel #59
0
    def update(self, id, title=None, content=None, post_mode=None,
               attachments=None, pin=None):
        """
        更新分享

        详情请参考
        http://docs.teambition.com/wiki/posts#posts-update

        :param id: 分享 ID
        :param title: 可选,标题
        :param content: 可选,内容
        :param post_mode: 可选,分享模式
        :param attachments: 可选,附件 ID 列表
        :param pin: 可选,置顶状态,True/False
        :return: 返回的 JSON 数据包
        """
        data = optionaldict(
            title=title,
            content=content,
            postMode=post_mode,
            attachments=attachments,
            pin=pin
        )
        return self._put(
            'api/posts/{0}'.format(id),
            data=data
        )
Beispiel #60
0
    def addpreentry(self,
                    name,
                    mobile,
                    pre_entry_time=None,
                    op_userid=None,
                    extend_info=None):
        """
        智能人事添加企业待入职员工

        :param name: 员工姓名
        :param mobile: 手机号
        :param pre_entry_time: 预期入职时间
        :param op_userid: 操作人userid
        :param extend_info: 扩展信息
        :return:
        """
        if isinstance(pre_entry_time, (datetime.date, datetime.datetime)):
            pre_entry_time = pre_entry_time.strftime(self.DATE_TIME_FORMAT)
        if isinstance(extend_info, dict):
            extend_info = json.dumps(extend_info)

        return self._top_request(
            "dingtalk.oapi.smartwork.hrm.employee.addpreentry", {
                "param":
                optionaldict({
                    "name": name,
                    "mobile": mobile,
                    "pre_entry_time": pre_entry_time,
                    "op_userid": op_userid,
                    "extend_info": extend_info
                })
            })