Exemplo n.º 1
0
    def check_drive_file_permission(self, user_access_token, file_token,
                                    file_type, perm):
        """判断协作者是否有某权限

        :type self: OpenLark
        :param user_access_token: user_access_token
        :type user_access_token: str
        :param file_token: 文件的 token
        :type file_token: str
        :param file_type: 文件类型
        :type file_type: DriveFileType
        :param perm: 权限
        :type perm: DriveFilePermission

        该接口用于根据 file_token 判断当前登录用户是否具有某权限

        https://open.feishu.cn/document/ukTMukTMukTM/uYzN3UjL2czN14iN3cTN
        """
        url = self._gen_request_url(
            '/open-apis/drive/permission/member/permitted')
        body = {
            'token': file_token,
            'type': converter_enum(file_type),
            'perm': converter_enum(perm),
        }
        res = self._post(url, body=body, auth_token=user_access_token)
        return res['data']['is_permitted']
Exemplo n.º 2
0
    def delete_drive_file(self, user_access_token, file_token, file_type):
        """删除云空间文件

        :type self: OpenLark
        :param user_access_token: user_access_token
        :type user_access_token: str
        :param file_token: 文件的 token
        :type file_token: str
        :param file_type: 文档类型,可选值为 doc 和 sheet
        :type file_type: DriveFileType
        :return: 文件夹元信息
        :rtype: DriveDeleteFile

        本文档包含两个接口,分别用于删除 Doc 和 Sheet,对应的文档类型请调用对应的接口

        文档只能被文档所有者删除,文档被删除后将会放到回收站里

        https://open.feishu.cn/document/ukTMukTMukTM/uATM2UjLwEjN14CMxYTN
        """
        if converter_enum(file_type) == 'doc':
            url = self._gen_request_url(
                '/open-apis/drive/explorer/v2/file/docs/{}'.format(file_token))
        elif converter_enum(file_type) == 'sheet':
            url = self._gen_request_url(
                '/open-apis/drive/explorer/v2/file/spreadsheets/{}'.format(
                    file_token))
        else:
            raise LarkInvalidArguments(
                msg='delete file type should be doc or sheet')

        res = self._delete(url, auth_token=user_access_token)
        return make_datatype(DriveDeleteFile, res['data'])
Exemplo n.º 3
0
    def add_drive_file_permission(self, user_access_token, file_token,
                                  file_type, members):
        """增加权限

        :type self: OpenLark
        :param user_access_token: user_access_token
        :type user_access_token: str
        :param file_token: 文件的 token
        :type file_token: str
        :param file_type: 文件类型
        :type file_type: DriveFileType
        :param members: 要添加的权限的人
        :type members: list[DriveFileUserPermission]
        :rtype: list[DriveFileUserPermission]

        该接口用于根据 file_token 给用户增加文档的权限

        https://open.feishu.cn/document/ukTMukTMukTM/uMzNzUjLzczM14yM3MTN
        """
        url = self._gen_request_url(
            '/open-apis/drive/permission/member/create')
        body = {
            'token': file_token,
            'type': converter_enum(file_type),
            'members': [i.as_dict() for i in members]
        }
        res = self._post(url, body=body, auth_token=user_access_token)
        if res['data'].get('is_all_success', False):
            return []

        return unmarshal_drive_user_permission(
            res['data']['fail_members'])  # type: List[DriveFileUserPermission]
Exemplo n.º 4
0
    def get_drive_file_permissions(self, user_access_token, file_token,
                                   file_type):
        """获取协作者列表

        :type self: OpenLark
        :param user_access_token: user_access_token
        :type user_access_token: str
        :param file_token: 文件的 token
        :type file_token: str
        :param file_type: 文件类型
        :type file_type: DriveFileType
        :rtype list[DriveFileUserPermission]

        该接口用于根据 file_token 查询协作者,目前包括人("user")和群("chat")

        你能获取到协作者列表的前提是你对该文档有权限

        https://open.feishu.cn/document/ukTMukTMukTM/uATN3UjLwUzN14CM1cTN
        """
        url = self._gen_request_url('/open-apis/drive/permission/member/list')
        body = {
            'type': converter_enum(file_type),
            'token': file_token,
        }
        res = self._post(url, body=body, auth_token=user_access_token)
        return unmarshal_drive_user_permission(
            res['data']['members'],
            open_id_type='user',
            open_id_key='member_open_id',
            chat_id_type='chat',
            chat_id_key='member_open_id'
        )  # type: List[DriveFileUserPermission]
Exemplo n.º 5
0
    def upload_approval_file(self, name, filetype, content):
        """审批所需要的文件上传

        :type self: OpenLark
        :param name: 文件名,需包含文件扩展名,如“文件.doc
        :type name: str
        :param filetype: 文件类型,只能是 image 和 attachment 之一
        :type filetype: ApprovalUploadFileType
        :param content: 文件,支持路径、bytes、BytesIO
        :return: 返回的第一个是可以用于审批的 code,第二个是图片或者文件的 URL
        :rtype: Tuple[str, str]
        """
        content = to_file_like(content)

        url = self._gen_request_url('/approval/openapi/v1/file/upload',
                                    app='approval')
        body = {
            'name': name,
            'type': converter_enum(filetype),
        }
        files = {'content': content}
        res = self._post(url=url,
                         body=body,
                         files=files,
                         with_tenant_token=True)
        data = res['data']
        code = data.get('code', '')  # type: str
        url = data.get('url', '')  # type: str
        return code, url
Exemplo n.º 6
0
    def merge_drive_sheet_cells(self, user_access_token, sheet_token, sheet_id, range, merge_type):
        """合并单元格

        :type self: OpenLark
        :param user_access_token: user_access_token
        :type user_access_token: str
        :param sheet_token: 文件的 token 列表
        :type sheet_token: str
        :param sheet_id: 作为表格唯一识别参数
        :type sheet_id: str
        :param range: 范围,形如:'A1:D2'
        :type range: str
        :param merge_type: lock 信息
        :type merge_type: DriveSheetMergeType
        :rtype: str

        该接口用于根据 sheet_token 和维度信息合并单元格;单次操作不超过5000行,100列。

        https://open.feishu.cn/document/ukTMukTMukTM/ukDNzUjL5QzM14SO0MTN
        """
        url = self._gen_request_url('/open-apis/sheet/v2/spreadsheets/{}/merge_cells'.format(sheet_token))
        body = {
            'range': join_range(sheet_id, range),
            'mergeType': converter_enum(merge_type),
        }

        self._post(url, body=body, auth_token=user_access_token)
Exemplo n.º 7
0
    def reply_meeting(self, room_id, uid, original_time, status):
        """回复会议室日程实例

        :type self: OpenLark
        :param room_id: 会议室的 ID
        :type room_id: str
        :param uid: 会议室的日程 ID
        :type uid: str
        :param original_time: 日程实例原始时间,非重复日程必为0。重复日程若为0则表示回复其所有实例,否则表示回复单个实例。
        :type original_time: int
        :param status: 回复状态,NOT_CHECK_IN 表示未签到,ENDED_BEFORE_DUE 表示提前结束
        :type status: MeetingReplyStatus
        :return: 查询会议室忙闲的起始时间(与请求参数完全相同), 查询会议室忙闲的结束时间(与请求参数完全相同), Dict['会议室ID', List[忙碌时间]]
        :rtype: (datetime.datetime, datetime.datetime, dict[str, list[RoomFreeBusy]])

        https://open.feishu.cn/document/ukTMukTMukTM/uIDOyUjLygjM14iM4ITN
        """
        body = {
            'room_id': room_id,
            'uid': uid,
            'original_time': original_time,
            'status': converter_enum(status),
        }
        url = self._gen_request_url('/open-apis/meeting_room/instance/reply')

        self._post(url, body=body, with_tenant_token=True)
Exemplo n.º 8
0
    def create_drive_file(self, user_access_token, folder_token, title,
                          file_type):
        """创建云空间文件

        :type self: OpenLark
        :param user_access_token: user_access_token
        :type user_access_token: str
        :param folder_token: 文件夹的 token
        :type folder_token: str
        :param title: 文档标题
        :type title: str
        :param file_type: 文档类型,可选值为 doc 和 sheet
        :type file_type: DriveFileType
        :return: 文件夹元信息
        :rtype: DriveCreateFile

        该接口用于根据 folder_token 创建 Docs或 Sheets 。

        https://open.feishu.cn/document/ukTMukTMukTM/uQTNzUjL0UzM14CN1MTN
        """
        url = self._gen_request_url(
            '/open-apis/drive/explorer/v2/file/{}'.format(folder_token))
        body = {
            'title':
            title,
            'type':
            converter_enum(file_type,
                           ranges=[DriveFileType.doc, DriveFileType.sheet]),
        }
        res = self._post(url, body=body, auth_token=user_access_token)
        return make_datatype(DriveCreateFile, res['data'])
Exemplo n.º 9
0
    def update_drive_file_permission(self,
                                     user_access_token,
                                     file_token,
                                     file_type,
                                     member,
                                     perm=DriveFilePermission.view,
                                     is_notify=None):
        """更新协作者权限

        :type self: OpenLark
        :param user_access_token: user_access_token
        :type user_access_token: str
        :param file_token: 文件的 token
        :type file_token: str
        :param file_type: 文件类型
        :type file_type: DriveFileType
        :param member: 成员
        :type member: DriveFileUser
        :param perm: 权限
        :type perm: DriveFilePermission
        :param is_notify: 是否通知
        :type is_notify: bool

        该接口用于根据 file_token 更新文档协作者的权限

        https://open.feishu.cn/document/ukTMukTMukTM/ucTN3UjL3UzN14yN1cTN
        """
        url = self._gen_request_url(
            '/open-apis/drive/permission/member/update')
        body = member.as_dict()
        body['token'] = file_token
        body['type'] = converter_enum(file_type)
        body['perm'] = converter_enum(perm)
        if is_notify is not None:
            body['notify_lark'] = is_notify
        self._post(url, body=body, auth_token=user_access_token)
Exemplo n.º 10
0
    def get_visible_apps(self, user_id=None, open_id=None, page_size=20, page_token='', lang=I18NType.zh_cn):
        """获取应用在企业内的可用范围

        :type self: OpenLark
        :param user_id: 目标用户 user_id,与 open_id 至少给其中之一,user_id 优先于 open_id
        :type user_id: str
        :param open_id: 目标用户 open_id
        :type open_id: str
        :param page_size: 本次拉取用户列表最大个数(最大值 1000 ,0 自动最大个数 )
        :type page_size: int
        :param page_token: 分页拉取用户列表起始位置标示,不填表示从头开始
        :type page_token: str
        :param lang: 优先展示的应用信息的语言版本(zh_cn:中文,en_us:英文,ja_jp:日文)
        :type lang: I18NType
        :return: 是否还有更多, page_token, page_size, 总数, 语言, 应用列表
        :rtype: (bool, str, int, int, I18NType, list[App])

        该接口用于查询应用在该企业内可以被使用的范围,只能被企业自建应用调用且需要“获取应用信息”权限。

        https://open.feishu.cn/document/ukTMukTMukTM/uIjM3UjLyIzN14iMycTN
        """
        url = self._gen_request_url('/open-apis/application/v1/user/visible_apps?')
        if user_id:
            url = '{}&user_id={}'.format(url, user_id)
        elif open_id:
            url = '{}&open_id={}'.format(url, open_id)
        else:
            raise LarkInvalidArguments(msg='empty user_id and open_id')
        if page_token:
            url = '{}&page_token={}'.format(url, page_token)
        if page_size:
            url = '{}&page_size={}'.format(url, page_size)
        if lang:
            url = '{}&lang={}'.format(url, converter_enum(lang))

        res = self._get(url, with_tenant_token=True)
        data = res['data']

        apps = [make_datatype(App, i) for i in data.get('app_list', [])]  # type: List[App]

        has_more = bool(data.get('has_more', False))  # type: bool
        lang = I18NType(data.get('lang', 'zh_cn'))  # type: I18NType
        page_size = data.get('page_size')  # type: int
        page_token = data.get('page_token')  # type: str
        total_count = data.get('total_count')  # type: int
        return has_more, page_token, page_size, total_count, lang, apps
Exemplo n.º 11
0
    def copy_drive_file(self,
                        user_access_token,
                        file_token,
                        file_type,
                        dst_folder_token,
                        dst_title,
                        permission_needed=False,
                        comment_needed=False):
        """复制云空间文件

        :type self: OpenLark
        :param user_access_token: user_access_token
        :type user_access_token: str
        :param file_token: 文件的 token
        :type file_token: str
        :param file_type: 文档类型,可选值为 doc 和 sheet
        :type file_type: DriveFileType
        :param dst_folder_token:目标文件夹 token
        :type dst_folder_token: str
        :param dst_title: 目标文档标题
        :type dst_title: str
        :param permission_needed: 同时复制权限
        :type permission_needed: bool
        :param comment_needed: 同时复制评论
        :type comment_needed: bool
        :return: 复制文件的返回值
        :rtype: DriveCopyFile

        该接口用于根据 file_token 复制 docs 或 sheets 。

        https://open.feishu.cn/document/ukTMukTMukTM/uYTNzUjL2UzM14iN1MTN
        """
        url = self._gen_request_url(
            '/open-apis/drive/explorer/v2/file/copy/files/{}'.format(
                file_token))
        body = {
            'type': converter_enum(file_type),
            'dstFolderToken': dst_folder_token,
            'dstName': dst_title,
            'permissionNeeded': permission_needed,
            'CommentNeeded': comment_needed
        }

        res = self._post(url, body=body, auth_token=user_access_token)
        return make_datatype(DriveCopyFile, res['data'])
Exemplo n.º 12
0
    def search_drive_file(self, user_access_token, key, owner_open_ids=None, chat_open_ids=None, docs_types=None,
                          count=50, offset=0):
        """文档搜索

        :type self: OpenLark
        :param user_access_token: user_access_token
        :type user_access_token: str
        :param key: 搜索的关键词
        :type key: str
        :param owner_open_ids: 文档所有人
        :type owner_open_ids: list[str]
        :param chat_open_ids: 文档所在群
        :type chat_open_ids: list[str]
        :param docs_types: 文档类型,支持:"doc", "sheet", "slide", "bitable", "mindnote", "file", "wiki"
        :type docs_types: list[DriveFileType]
        :param count: 个数
        :type count: int
        :param offset: 偏移
        :type offset: int
        :return: 文件元信息
        :rtype: (bool, int, list[DriveFileMeta])

        该接口用于根据搜索条件进行文档搜索

        https://open.feishu.cn/document/ukTMukTMukTM/ugDM4UjL4ADO14COwgTN
        """
        url = self._gen_request_url('/open-apis/suite/docs-api/search/object')
        body = {
            'search_key': key,
            'count': count,
            'offset': offset,
        }
        if owner_open_ids:
            body['owner_ids'] = owner_open_ids
        if chat_open_ids:
            body['chat_ids'] = chat_open_ids
        if docs_types:
            body['docs_types'] = [converter_enum(i) for i in docs_types]
        res = self._post(url, body=body, auth_token=user_access_token)
        has_more = res['data']['has_more']
        total = res['data']['total']
        entities = [make_datatype(DriveFileMeta, i) for i in res['data']['docs_entities']]
        return has_more, total, entities
Exemplo n.º 13
0
    def get_installed_apps(self, page_size=20, page_token='', lang=I18NType.zh_cn, status=-1):
        """获取企业安装的应用

        :type self: OpenLark
        :param page_size: 本次拉取用户列表最大个数(最大值 1000 ,0 自动最大个数 )
        :type page_size: int
        :param page_token: 分页拉取用户列表起始位置标示,不填表示从头开始
        :type page_token: str
        :param lang: 优先展示的应用信息的语言版本(zh_cn:中文,en_us:英文,ja_jp:日文)
        :type lang: I18NType
        :param status: 要返回的应用的状态,0:停用;1:启用;-1:全部
        :type status: int
        :return: 是否还有更多, page_token, page_size, 总数, 语言, 应用列表
        :rtype: (bool, str, int, int, I18NType, list[App])

        该接口用于查询企业安装的应用列表,只能被企业自建应用调用且需要“获取应用信息”权限。

        https://open.feishu.cn/document/ukTMukTMukTM/uYDN3UjL2QzN14iN0cTN
        """
        url = self._gen_request_url('/open-apis/application/v3/app/list?')
        if page_token:
            url = '{}&page_token={}'.format(url, page_token)
        if page_size:
            url = '{}&page_size={}'.format(url, page_size)
        if lang:
            url = '{}&lang={}'.format(url, converter_enum(lang))
        if status in [0, 1, -1]:
            url = '{}&status={}'.format(url, status)

        res = self._get(url, with_tenant_token=True)
        data = res['data']

        apps = [make_datatype(App, i) for i in data.get('app_list', [])]  # type: List[App]

        has_more = bool(data.get('has_more', False))  # type: bool
        lang = I18NType(data.get('lang', 'zh_cn'))  # type: I18NType
        page_size = data.get('page_size')  # type: int
        page_token = data.get('page_token')  # type: str
        total_count = data.get('total_count')  # type: int
        return has_more, page_token, page_size, total_count, lang, apps
Exemplo n.º 14
0
    def transfer_drive_file_owner(self,
                                  user_access_token,
                                  file_token,
                                  file_type,
                                  owner,
                                  remove_old_owner=False,
                                  notify_old_owner=True):
        """转移拥有者

        :type self: OpenLark
        :param user_access_token: user_access_token
        :type user_access_token: str
        :param file_token: 文件的 token
        :type file_token: str
        :param file_type: 文件类型
        :type file_type: DriveFileType
        :param owner: 要转移的人
        :type owner: DriveFileUser
        :param remove_old_owner: 转移后删除旧 owner 的权限,默认为 False
        :type remove_old_owner: bool
        :param notify_old_owner: 通知旧 owner,默认为 True
        :type notify_old_owner: bool

        该接口用于根据文档信息和用户信息转移文档的所有者。

        https://open.feishu.cn/document/ukTMukTMukTM/uQzNzUjL0czM14CN3MTN
        """
        url = self._gen_request_url(
            '/open-apis/drive/permission/member/transfer')
        body = {
            'type': converter_enum(file_type),
            'token': file_token,
            'owner': owner.as_dict(),
            'remove_old_owner': remove_old_owner,
            'cancel_notify': not notify_old_owner
        }
        self._post(url, body=body, auth_token=user_access_token)
Exemplo n.º 15
0
    def delete_drive_file_permission(self, user_access_token, file_token,
                                     file_type, member):
        """移除协作者权限

        :type self: OpenLark
        :param user_access_token: user_access_token
        :type user_access_token: str
        :param file_token: 文件的 token
        :type file_token: str
        :param file_type: 文件类型
        :type file_type: DriveFileType
        :param member: 成员
        :type member: DriveFileUser

        该接口用于根据 file_token 移除文档协作者的权限

        https://open.feishu.cn/document/ukTMukTMukTM/uYTN3UjL2UzN14iN1cTN
        """
        url = self._gen_request_url(
            '/open-apis/drive/permission/member/delete')
        body = member.as_dict()
        body['token'] = file_token
        body['type'] = converter_enum(file_type)
        self._post(url, body=body, auth_token=user_access_token)
Exemplo n.º 16
0
    def update_drive_file_public_permission(self,
                                            user_access_token,
                                            file_token,
                                            file_type,
                                            copy_print_export_status=None,
                                            comment=None,
                                            tenant_shareable=None,
                                            link_share_entity=None,
                                            external_access=None,
                                            invite_external=None):
        """更新文档公共设置

        :type self: OpenLark
        :param user_access_token: user_access_token
        :type user_access_token: str
        :param file_token: 文件的 token
        :type file_token: str
        :param file_type: 文件类型
        :type file_type: DriveFileType
        :param copy_print_export_status: 可创建副本/打印/导出/复制设置(不传则保持原值):
                                            true - 所有可访问此文档的用户
                                            false - 有编辑权限的用户
        :type copy_print_export_status: bool
        :param comment: 可评论设置(不传则保持原值):
                            true - 所有可访问此文档的用户
                            false - 有编辑权限的用户
        :type comment: bool
        :param tenant_shareable: 租户内用户是否有共享权限(不传则保持原值)
        :type tenant_shareable: bool
        :param link_share_entity: 链接共享(不传则保持原值):
                                    "tenant_readable" - 组织内获得链接的人可阅读
                                    "tenant_editable" - 组织内获得链接的人可编辑
                                    "anyone_readable" - 获得链接的任何人可阅读
                                    "anyone_editable" - 获得链接的任何人可编辑
        :type link_share_entity: DriveFilePublicLinkSharePermission
        :param external_access: 是否允许分享到租户外开关(不传则保持原值)
        :type external_access: bool
        :param invite_external: 非owner是否允许邀请外部人(不传则保持原值)
        :type invite_external: bool

        该接口用于根据 file_token 更新文档的公共设置

        https://open.feishu.cn/document/ukTMukTMukTM/ukTM3UjL5EzN14SOxcTN
        """
        url = self._gen_request_url(
            '/open-apis/drive/permission/public/update')
        body = {
            'token': file_token,
            'type': converter_enum(file_type),
        }
        if copy_print_export_status is not None:
            body['copy_print_export_status'] = copy_print_export_status
        if comment is not None:
            body['comment'] = comment
        if tenant_shareable is not None:
            body['tenant_shareable'] = tenant_shareable
        if link_share_entity is not None:
            body['link_share_entity'] = link_share_entity.value
        if external_access is not None:
            body['external_access'] = external_access
        if invite_external is not None:
            body['invite_external'] = invite_external
        self._post(url, body=body, auth_token=user_access_token)