def __init__(self, token_manager): """ init the UserManager :param AccessTokenManager token_manager: instance of AccessTokenManager """ self.token_manager = token_manager self.request_manager = RequestManager()
def __init__(self, token_manager, agent_id): """ init the MessageManager :param AccessTokenManager token_manager: instance of AccessTokenManager :param agent_id: Number 企业自建应用是微应用agentId """ self.token_manager = token_manager self.request_manager = RequestManager() self.agent_id = agent_id
class MessageManager(): """ Role Manage class, init with AccessTokenManager instance """ def __init__(self, token_manager, agent_id): """ init the MessageManager :param AccessTokenManager token_manager: instance of AccessTokenManager :param agent_id: Number 企业自建应用是微应用agentId """ self.token_manager = token_manager self.request_manager = RequestManager() self.agent_id = agent_id def asyncsend_text_message(self, text, userid_list=None, dept_id_list=None, to_all_user=None): """ 异步发送文本通知,接口返回成功并不表示用户收到通知,需要通过“查询工作通知消息的发送结果”接口查询是否给用户发送成功 :param text: String 消息内容 :param userid_list: String 可选 (userid_list,dept_id_list, to_all_user必须有一个不能为空) 'zhangsan,lisi' :param dept_id_list: String 可选 '123,456' :param to_all_user: Boolean 可选 是否发送给企业全部用户 :return: { 'errcode': 0, 'errmsg': 'ok', 'task_id': 123 } """ if (not userid_list) and (not dept_id_list) and (not to_all_user): to_all_user = True extra_data = { 'agent_id': self.agent_id, 'msg': { 'msgtype': 'text', 'text': { 'content': text } }, 'userid_list': userid_list, 'dept_id_list': dept_id_list, 'to_all_user': to_all_user } return self.request_manager.post( request_url=constants.MSG_SEND_URL, request_params={'access_token': self.token()}, request_data=extra_data, ) def asyncsend_image_message(self, media_id, userid_list=None, dept_id_list=None, to_all_user=None): """ 异步发送图片通知,接口返回成功并不表示用户收到通知,需要通过“查询工作通知消息的发送结果”接口查询是否给用户发送成功 :param media_id: String 图片上传得到的media_id :param userid_list: String 可选(userid_list,dept_id_list, to_all_user必须有一个不能为空) 'zhangsan,lisi' :param dept_id_list: String 可选 '123,456' :param to_all_user: Boolean 可选 是否发送给企业全部用户 :return: { 'errcode': 0, 'errmsg': 'ok', 'task_id': 123 } """ if (not userid_list) and (not dept_id_list) and (not to_all_user): to_all_user = True extra_data = { 'agent_id': self.agent_id, 'msg': { 'msgtype': 'image', 'image': { 'media_id': media_id } }, 'userid_list': userid_list, 'dept_id_list': dept_id_list, 'to_all_user': to_all_user } return self.request_manager.post( request_url=constants.MSG_SEND_URL, request_params={'access_token': self.token()}, request_data=extra_data, ) def asyncsend_file_message(self, media_id, userid_list=None, dept_id_list=None, to_all_user=None): """ 异步发送文件通知,接口返回成功并不表示用户收到通知,需要通过“查询工作通知消息的发送结果”接口查询是否给用户发送成功 :param media_id: String 文件上传得到的media_id :param userid_list: String 可选(userid_list,dept_id_list, to_all_user必须有一个不能为空) 'zhangsan,lisi' :param dept_id_list: String 可选 '123,456' :param to_all_user: Boolean 可选 是否发送给企业全部用户 :return: { 'errcode': 0, 'errmsg': 'ok', 'task_id': 123 } """ if (not userid_list) and (not dept_id_list) and (not to_all_user): to_all_user = True extra_data = { 'agent_id': self.agent_id, 'msg': { 'msgtype': 'file', 'file': { 'media_id': media_id } }, 'userid_list': userid_list, 'dept_id_list': dept_id_list, 'to_all_user': to_all_user } return self.request_manager.post( request_url=constants.MSG_SEND_URL, request_params={'access_token': self.token()}, request_data=extra_data, ) def get_message_send_progress(self, task_id): """ 查询工作通知消息的发送进度 :param task_id:Number 发送消息时钉钉返回的任务id :return:{ 'errcode': 0, 'errmsg': 'ok', 'progress': { 'progress_in_percent': 100, 'status': 2 #(任务执行状态,0=未开始,1=处理中,2=处理完毕) } } """ extra_data = {'agent_id': self.agent_id, 'task_id': task_id} return self.request_manager.post( request_url=constants.MSG_GET_SEND_PROGRESS_URL, request_params={'access_token': self.token()}, request_data=extra_data, ) def get_message_send_result(self, task_id): """ 查询工作通知消息的发送结果 :param task_id: Number 异步任务的id :return:{ 'send_result': { 'invalid_user_id_list': 'zhangsan,lisi', # 因发送消息过于频繁或超量而被流控过滤后实际未发送的userid。未被限流的接收者仍会被成功发送。 'forbidden_user_id_list': 'zhangsan,lisi', 'failed_user_id_list': 'zhangsan,lisi', 'read_user_id_list': 'zhangsan,lisi', 'unread_user_id_list': 'zhangsan,lisi', 'invalid_dept_id_list': '1,2,3' }, 'errcode': 0, 'errmsg': 'ok' } """ extra_data = {'agent_id': self.agent_id, 'task_id': task_id} return self.request_manager.post( request_url=constants.MSG_GET_SEND_RESULT_URL, request_params={'access_token': self.token()}, request_data=extra_data, ) def token(self): """ get_access_token for short :return:access_token """ return self.token_manager.get_access_token()
class UserManager(): """ User Manage class, init with AccessTokenManager instance """ def __init__(self, token_manager): """ init the UserManager :param AccessTokenManager token_manager: instance of AccessTokenManager """ self.token_manager = token_manager self.request_manager = RequestManager() def get_user_count(self, onlyactive=False): """ 获取企业员工人数 :param:onlyActive:False:包含未激活钉钉的人员数量 True:不包含未激活钉钉的人员数量 :return:{ 'count': 6, 'errcode': 0, 'errmsg': 'ok' } """ onlyactive_opt = 1 if onlyactive else 0 return self.request_manager.get( request_url=constants.USER_GET_USER_COUNT_URL, request_params={ 'access_token': self.token(), 'onlyActive': onlyactive_opt }) def add_user(self, name, mobile, departments, **kwargs): """ :param str name: 成员名称。长度为1~64个字符 :param str mobile: 手机号码。企业内必须唯一 :param [int] departments: 成员所属部门id列表 :returns: { 'errcode': 0, 'errmsg': 'created', 'userid': 'zhangsan' } """ userdata = { 'name': name, 'mobile': mobile, 'department': departments, } userdata.update(kwargs) return self.request_manager.post( request_url=constants.USER_CREATE_URL, request_params={'access_token': self.token()}, request_data=userdata, ) def delete_user(self, uid): """ :param str uid: 员工唯一标识 :returns{ 'errcode': 0, 'errmsg': 'deleted' } """ return self.request_manager.get(request_url=constants.USER_DELETE_URL, request_params={ 'access_token': self.token(), 'userid': uid }) def update_user(self, uid, **kwargs): """ 如果非必须的字段未指定,则钉钉后台不改变该字段之前设置好的值 :param uid: 员工唯一标识 :param kwargs: 需要更新的参数列表 { 'userid': 'zhangsan', 'name': '张三', 'department': [1, 2], 'orderInDepts': '{1:10}', 'position': '产品经理', 'mobile': '15913215421', 'tel': '010-123333', 'workPlace':'', 'remark': '', 'email': '*****@*****.**', 'orgEmail': '*****@*****.**', 'jobnumber': '111111', 'isHide': false, 'isSenior': false, 'extattr': { '爱好':'旅游', '年龄':'24' } } :return:{ 'errcode': 0, 'errmsg': 'updated' } """ userdata = { 'userid': uid, } userdata.update(kwargs) return self.request_manager.post( request_url=constants.USER_UPDATE_URL, request_params={'access_token': self.token()}, request_data=userdata, ) def get_user_detail(self, uid): """ :param str uid: 员工唯一标识 :returns: { 'errcode': 0, 'errmsg': 'ok', 'userid': 'zhangsan', 'name': '张三', 'tel': '010-123333', 'workPlace' :'', 'remark': '', 'mobile': '13800000000', 'email': '*****@*****.**', 'active': true, 'orderInDepts': '{1:10, 2:20}', 'isAdmin': false, 'isBoss': false, 'openId': 'WsUDaq7DCVIHc6z1GAsYDSA', 'unionid': 'cdInjDaq78sHYHc6z1gsz', 'isLeaderInDepts' : '{1:true, 2:false}', 'isHide': false, 'department': [1, 2], 'position': '工程师', 'avatar': 'dingtalk.com/abc.jpg', 'jobnumber': '111111', 'isSenior': False, 'stateCode': '86', 'id': 394299625, 'position': '',#职位信息 'roles': [{u'groupName': '岗位', 'type': 0, 'id': 394299625, 'name': '经理'}], } """ return self.request_manager.get( request_url=constants.USER_GET_DETAIL_URL, request_params={ 'access_token': self.token(), 'userid': uid }) def token(self): """ get_access_token for short :return:access_token """ return self.token_manager.get_access_token()
class RoleManager(): """ Role Manage class, init with AccessTokenManager instance """ def __init__(self, token_manager): """ init the RoleManager :param AccessTokenManager token_manager: instance of AccessTokenManager """ self.token_manager = token_manager self.request_manager = RequestManager() def get_roles_list(self, size, offset): """ 获取角色列表 :param size: Number 分页大小,最大值200 :param offset: Number 分页偏移 :return: { 'errcode':0, 'errmsg':'ok', 'result':{ 'hasMore':false, 'list':[ { 'name':'默认', 'groupId':1, 'roles':[ { 'name':'管理员', 'id':1 } ] } ] } } """ extra_data = { 'size': size, 'offset': offset, } return self.request_manager.post( request_url=constants.ROLE_GET_ROLES_LIST, request_params={'access_token': self.token()}, request_data=extra_data) def get_role_userlist(self, role_id, size, offset): """ 获取角色下的员工列表 :param role_id: Number 角色ID :param size: Number 分页大小 :param offset: 分页偏移 :return:{ 'errcode':0, 'errmsg':'ok', 'result':{ 'hasMore':false, 'nextCursor':100,#下次拉取数据的游标 'list':[ { 'userid':'manager7978', 'name':'小钉' } ] } } """ extra_data = { 'role_id': role_id, 'size': size, 'offset': offset, } return self.request_manager.post( request_url=constants.ROLE_GET_ROLE_USERLIST, request_params={'access_token': self.token()}, request_data=extra_data) def get_role_group(self, group_id): """ 获取角色组 :param group_id:Number 角色组Id :return:{ 'role_group':{ 'roles':[ { 'role_id':1, 'role_name':'出纳' } ], 'group_name':'财务' }, 'errcode':1, 'errmsg':'ok' } """ extra_data = {'group_id': group_id} return self.request_manager.post( request_url=constants.ROLE_GET_ROLE_GROUP, request_params={'access_token': self.token()}, request_data=extra_data) def get_role_detail(self, role_id): """ 获取角色详情 :param role_id: 角色Id :return: { 'role':{ 'name':'财务', 'groupId':1002 }, 'errcode':0, 'errmsg':'成功' } """ extra_data = {'roleId': role_id} return self.request_manager.post( request_url=constants.ROLE_GET_ROLE_DETAIL, request_params={'access_token': self.token()}, request_data=extra_data) def create_role(self, role_name, group_id): """ 创建角色 :param role_name:String 角色名称 :param group_id: Number 角色组id :return: { 'roleId':1, 'errcode': 0, 'errmsg': 'ok' } """ extra_data = {'roleName': role_name, 'groupId': group_id} return self.request_manager.post( request_url=constants.ROLE_CREATE_ROLE, request_params={'access_token': self.token()}, request_data=extra_data) def update_role(self, role_name, role_id): """ 更新角色 :param role_name: String 角色名称 :param role_id: Number 角色id :return: { 'errcode':0, 'errmsg':'ok', } """ extra_data = { 'roleName': role_name, 'roleId': role_id, } return self.request_manager.post( request_url=constants.ROLE_UPDATE_ROL, request_params={'access_token': self.token()}, request_data=extra_data) def delete_role(self, role_id): """ 删除角色 :param role_id: Number 角色ID :return:{ 'errcode':0, 'errmsg':'ok', } """ extra_data = { 'role_id': role_id, } return self.request_manager.post( request_url=constants.ROLE_DELETE_ROLE, request_params={'access_token': self.token()}, request_data=extra_data) def create_role_group(self, name): """ 创建角色组 :param name:String 角色组名称 :return:{ 'groupId':11, 'errcode': 0, 'errmsg': 'ok' } """ extra_data = {'name': name} return self.request_manager.post( request_url=constants.ROLE_CREATE_ROLE_GROUP, request_params={'access_token': self.token()}, request_data=extra_data) def add_users_roles(self, role_ids, user_ids): """ 批量添加员工到角色列表 :param role_ids: String 1,2,3 角色id list,最大列表长度:20 :param user_ids: String a,b,c 员工id list,最大列表长度:100 :return: { 'errcode':0, 'errmsg':'成功' } """ extra_data = {'roleIds': role_ids, 'userIds': user_ids} return self.request_manager.post( request_url=constants.ROLE_ADD_USERS_ROLES, request_params={'access_token': self.token()}, request_data=extra_data) def delete_users_roles(self, role_ids, user_ids): """ 批量删除员工的角色 :param role_ids: String 1,2,3 角色id list,最大列表长度:20 :param user_ids: String a,b,c 员工id list,最大列表长度:100 :return: { 'errcode':0, 'errmsg':'成功' } """ extra_data = {'roleIds': role_ids, 'userIds': user_ids} return self.request_manager.post( request_url=constants.ROLE_DEL_USERS_ROLES, request_params={'access_token': self.token()}, request_data=extra_data) def token(self): """ get_access_token for short :return:access_token """ return self.token_manager.get_access_token()
class DepartmentManager(): """ Department Manage class, init with AccessTokenManager instance """ def __init__(self, token_manager): """ init the DepartmentManager :param AccessTokenManager token_manager: instance of AccessTokenManager """ self.token_manager = token_manager self.request_manager = RequestManager() def get_subdep_listids(self, department_id): """ 获取直属子部门id列表 :param department_id:stirng 部门id :return:{ 'errcode': 0, 'errmsg': 'ok', 'sub_dept_id_list': [ 2,3,4,5 ] } """ return self.request_manager.get( request_url=constants.DEPARTMENT_GET_SUB_DEP_LIST, request_params={ 'access_token': self.token(), 'id': department_id }) def list_parent_deps(self, department_id='1'): """ 假设部门的组织结构如下: 1 |->123 |->456 |->789 当传入部门id为789时,返回的结果按顺序依次为当前部门id及其所有父部门的ID,直到根部门,如[789,456,123,1] :param department_id:string 部门id :return:{ 'errcode': 0, 'errmsg': 'ok', 'parentIds':[789,456,123,1] } """ return self.request_manager.get( request_url=constants.DEPARTMENT_LIST_PARENT_DEPS, request_params={ 'access_token': self.token(), 'id': department_id }) def get_user_list_parentdeps(self, userid=''): """ 假设用户所属部门的组织结构如下 1 |->123 |->456 ->员工A |->789 ->员工A 当传入员工A的userId时,返回的结果按顺序依次为其所有父部门的ID,直到根部门,如[[456,123,1],[789,1]]。 :param userid: 查询的用户id :return:{ 'errcode': 0, 'errmsg': 'ok', 'department':[[456,123,1],[789,1]] } """ return self.request_manager.get( request_url=constants.DEPARTMENT_USER_LIST_PARENT_DEPS, request_params={ 'access_token': self.token(), 'userId': userid }) def get_users(self, department_id, offset, size, order='custom'): """ 获取部门下员工的详情,不递归 :param: { department_id:long 获取的部门id offset:long 支持分页查询,与size参数同时设置时才生效,此参数代表偏移量 size:int 支持分页查询,与offset参数同时设置时才生效,此参数代表分页大小,最大100 order:支持分页查询,部门成员的排序规则,默认不传是按自定义排序; entry_asc:代表按照进入部门的时间升序, entry_desc:代表按照进入部门的时间降序, modify_asc:代表按照部门信息修改时间升序, modify_desc:代表按照部门信息修改时间降序, custom:代表用户定义(未定义时按照拼音)排序 } :returns: { 'errcode': 0, 'errmsg': 'ok', 'hasMore': False, 'userlist':[ { 'userid': 'zhangsan', 'dingId': 'dwdded', 'mobile': '13122222222', 'tel' : '010-123333', 'workPlace' :'', 'remark' : '', 'order' : 1, 'isAdmin': True, 'isBoss': False, 'isHide': True, 'isLeader': True, 'name': '张三', 'active': True, 'department': [1, 2], 'position': '工程师', 'email': '*****@*****.**', 'avatar': './dingtalk/abc.jpg', 'jobnumber': '111111', 'extattr': { '爱好':'旅游', '年龄':'24' } } ] } """ return self.request_manager.get( request_url=constants.DEPARTMENT_GET_USERS_URL, request_params={ 'access_token': self.token(), 'department_id': department_id, 'offset': offset, 'size': size, 'order': order, }) def get_users_brief(self, department_id, offset, size, order='custom'): """ 获取部门下员工的userid,name的list,不递归 :param: { department_id:long 获取的部门id offset:long 支持分页查询,与size参数同时设置时才生效,此参数代表偏移量 size:int 支持分页查询,与offset参数同时设置时才生效,此参数代表分页大小,最大100 order:支持分页查询,部门成员的排序规则,默认不传是按自定义排序; entry_asc:代表按照进入部门的时间升序, entry_desc:代表按照进入部门的时间降序, modify_asc:代表按照部门信息修改时间升序, modify_desc:代表按照部门信息修改时间降序, custom:代表用户定义(未定义时按照拼音)排序 } :returns: { 'errcode': 0, 'errmsg': 'ok', 'hasMore': False, 'userlist': [ { 'userid': 'manager8659', 'name': '张三' }, { 'userid': 'zhangsan1', 'name': '张三' } ], } """ return self.request_manager.get( request_url=constants.DEPARTMENT_USER_SIMPLELIST_URL, request_params={ 'access_token': self.token(), 'department_id': department_id, 'offset': offset, 'size': size, 'order': order, }) def get_subdep_list(self, department_id, fetch_child=True): """ 获取子部门列表 :param department_id:string 部门id :param fetch_child: 是否递归子部门 :return:{ 'errcode': 0, 'errmsg': 'ok', 'department': [ { 'id': 2, 'name': '钉钉事业部', 'parentid': 1, 'createDeptGroup': true, 'autoAddUser': true },{ 'id': 3, 'name': '服务端开发组', 'parentid': 2, 'createDeptGroup': false, 'autoAddUser': false } ] } """ return self.request_manager.get( request_url=constants.DEPARTMENT_GET_DEP_LIST, request_params={ 'access_token': self.token(), 'id': department_id, 'fetch_child': fetch_child, }) def get_dep_detail(self, department_id): """ 获取部门详情 :param department_id:string 部门id :return: { 'errcode': 0, 'errmsg': 'ok', 'id': 2, 'name': '钉钉事业部', 'order' : 10, 'parentid': 1, 'createDeptGroup': true, 'autoAddUser': true, 'deptHiding' : true, 'deptPermits' : '3|4', 'userPermits' : 'userid1|userid2', 'outerDept' : true, 'outerPermitDepts' : '1|2', 'outerPermitUsers' : 'userid3|userid4', 'orgDeptOwner' : 'manager1122', 'deptManagerUseridList' : 'manager1122|manager3211', 'sourceIdentifier' : 'source' } """ return self.request_manager.get( request_url=constants.DEPARTMENT_GET_DETAIL, request_params={ 'access_token': self.token(), 'id': department_id, }) def create_dep(self, parent_id, name, **kwargs): """ 创建部门 :param parent_id:父部门id :param name: 部门名称 :param kwargs:{ 'order': '1', 'createDeptGroup': true, 'deptHiding' : true, 'deptPermits' : '3|4', 'userPermits' : 'userid1|userid2', 'outerDept' : true, 'outerPermitDepts' : '1|2', 'outerPermitUsers' : 'userid3|userid4', 'sourceIdentifier' : 'source' } :return:{ 'errcode': 0, 'errmsg': 'created', 'id': 2 } """ createdata = { 'name': name, 'parentid': parent_id, } createdata.update(kwargs) return self.request_manager.post( request_url=constants.DEPARTMENT_CREATE_DEP, request_params={'access_token': self.token()}, request_data=createdata, ) def update_dep(self, department_id, **kwargs): """ 更新部门信息 :param department_id: string 部门id :param kwargs:{ 'name': '钉钉事业部', 'parentid': '1', 'order': '1', 'id': 1, 'createDeptGroup': true,#是否创建一个关联此部门的企业群 'autoAddUser': true,#如果有新人加入部门是否会自动加入部门群 'deptManagerUseridList': 'manager1111|2222', 'deptHiding' : true, 'deptPermits' : '3|4', 'userPermits' : 'userid1|userid2', 'outerDept' : true, 'outerPermitDepts' : '1|2', 'outerPermitUsers' : 'userid3|userid4', 'orgDeptOwner': 'manager1111', 'sourceIdentifier' : 'source' } :return:{ 'errcode': 0, 'errmsg': 'ok', 'id': 61602002 #更新后的部门id } """ updatedata = { 'id': department_id, } updatedata.update(kwargs) return self.request_manager.post( request_url=constants.DEPARTMENT_UPDATE_DEP, request_params={'access_token': self.token()}, request_data=updatedata, ) def delete_dep(self, department_id): """ 删除部门 :param department_id:string 部门id(注:不能删除根部门;不能删除含有子部门、成员的部门) :return:{ 'errcode': 0, 'errmsg': 'ok' } """ return self.request_manager.get( request_url=constants.DEPARTMENT_DEL_DEP, request_params={ 'access_token': self.token(), 'id': department_id }) def token(self): """ get_access_token for short :return:access_token """ return self.token_manager.get_access_token()