ad-password-self-service/utils/feishu/api_calendar.py

384 lines
15 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# coding: utf-8
from __future__ import absolute_import, division, print_function, unicode_literals
from typing import TYPE_CHECKING, Any, Dict, List, Tuple
from utils.feishu.dt_calendar import Calendar, CalendarAttendee, CalendarEvent
from utils.feishu.dt_enum import CalendarEventVisibility, CalendarRole
from utils.feishu.dt_help import make_datatype
if TYPE_CHECKING:
from utils.feishu.api import OpenLark
from six import string_types
"""
page_token && sync_token
使用 page_token/sync_token 可以方便开发者以“分页”的形式获取日历列表。
max_results 表示一个分页最多包含多少个日历。
假如当次请求返回的结果未包含最后一个日历response 中会携带 page_token代表当前分页
下次请求时带上此 page_token 可以访问下个分页,依此类推。
若 response 中携带了 sync_token代表当次请求已经是最后分页。若以后还有新增日历可以通过携带 sync_token 继续访问。
"""
class APICalendarMixin(object):
def get_calendar_by_id(self, calendar_id):
"""获取日历
:type self: OpenLark
:param calendar_id: 日历 ID来源于 URL 路径,创建日历后也会返回
:type calendar_id: str
:return: 日历的对象 Calendar
:rtype: Calendar
该接口用于根据日历 ID 获取日历信息。
https://open.feishu.cn/document/ukTMukTMukTM/uMDN04yM0QjLzQDN
"""
url = self._gen_request_url('/open-apis/calendar/v3/calendar_list/{}'.format(calendar_id))
res = self._get(url, with_tenant_token=True, success_code=200000)
data = res.get('data', {})
return make_datatype(Calendar, data)
def get_calendar_list(self,
max_results=500,
page_token='',
sync_token=''):
"""获取日历列表
:type self: OpenLark
:param max_results: 一次请求要求返回最大数,该参数不能大于 1000默认 500
:type max_results: int
:param page_token: 用于标志当次请求从哪页开始90 天有效期
:type page_token: str
:param sync_token: 表示从上次返回的截止页起返回结果90 天有效期
:type sync_token: str
:return: 两个分页参数,和日历对象 Calendar 的列表
:rtype: Tuple[str, str, List[Calendar]]
该接口用于获取应用在企业内的日历列表。
https://open.feishu.cn/document/ukTMukTMukTM/uMTM14yMxUjLzETN
"""
if max_results > 1000:
max_results = 1000
url = self._gen_request_url('/open-apis/calendar/v3/calendar_list?max_results={}'.format(max_results))
if page_token:
url = '{}&page_token={}'.format(url, page_token)
if sync_token:
url = '{}&sync_token={}'.format(url, sync_token)
res = self._get(url, with_tenant_token=True, success_code=200000)
data = res.get('data', [])
page_token = res.get('page_token', '')
sync_token = res.get('sync_token', '')
calendar_list = [make_datatype(Calendar, i) for i in data]
return page_token, sync_token, calendar_list
def create_calendar(self,
summary,
description='',
is_private=False,
default_access_role=CalendarRole.free_busy_reader):
"""创建日历
:type self: OpenLark
:param summary: 日历标题,最大长度为 256
:type summary: str
:param description: 日历描述,最大长度为 256
:type description: str
:param is_private: 是否为私有日历私有日历不可被搜索默认为false
:param default_access_role: 表示用户的默认访问权限。取值如下:
reader: 订阅者,可查看日程详情
free_busy_reader: 游客,只能看到"忙碌/空闲"
:type default_access_role: CalendarRole
:return: 日历的对象 Calendar
:rtype: Calendar
该接口用于为应用在企业内创建一个日历。
https://open.feishu.cn/document/ukTMukTMukTM/uQTM14CNxUjL0ETN
"""
url = self._gen_request_url('/open-apis/calendar/v3/calendars')
body = {
'summary': summary,
'description': description,
'is_private': is_private,
'default_access_role': default_access_role.value
}
res = self._post(url, body=body, with_tenant_token=True, success_code=200000)
data = res.get('data', {})
return make_datatype(Calendar, data)
def delete_calendar_by_id(self, calendar_id):
"""删除日历
:type self: OpenLark
:param calendar_id: 日历 ID
:type calendar_id: str
该接口用于删除应用在企业内的指定日历。
https://open.feishu.cn/document/ukTMukTMukTM/uUTM14SNxUjL1ETN
"""
url = self._gen_request_url('/open-apis/calendar/v3/calendars/{}'.format(calendar_id))
self._delete(url, with_tenant_token=True, success_code=200000)
def update_calendar_by_id(self,
calendar_id,
summary=None,
description=None,
is_private=None,
default_access_role=None):
"""更新日历
:type self: OpenLark
:param calendar_id: 日历 ID
:type calendar_id: str
:param summary: 日历标题,最大长度为 256
:type summary: str
:param description: 日历描述,最大长度为 256
:type description: str
:param is_private: 是否为私有日历私有日历不可被搜索默认为false
:type is_private: bool
:param default_access_role: 表示用户的默认访问权限。取值如下:
reader: 订阅者,可查看日程详情
free_busy_reader: 游客,只能看到"忙碌/空闲"
:type default_access_role: CalendarRole
:return: Calendar 对象
:rtype: Calendar
该接口用于修改指定日历的信息。
https://open.feishu.cn/document/ukTMukTMukTM/uYTM14iNxUjL2ETN
"""
url = self._gen_request_url('/open-apis/calendar/v3/calendars/{}'.format(calendar_id))
body = {}
for k, v in {
'summary': summary,
'description': description,
'is_private': is_private,
'default_access_role': default_access_role.value if default_access_role else None,
}.items():
if v is not None:
body[k] = v
res = self._patch(url, body, with_tenant_token=True, success_code=200000)
data = res['data']
return make_datatype(Calendar, data)
def _gen_calendar_event(self, data):
"""生成 CalendarEvent
:rtype CalendarEvent
"""
return CalendarEvent(
id=data.get('id', ''),
summary=data.get('summary', ''),
description=data.get('description', ''),
start=data.get('start', {}).get('time_stamp', 0),
end=data.get('end', {}).get('time_stamp', 0),
visibility=CalendarEventVisibility(data.get('visibility', 'default')),
attendees=[make_datatype(CalendarAttendee, i) for i in (data.get('attendees') or [])]
)
def get_calendar_event(self, calendar_id, event_id):
"""获取日程
:type self: OpenLark
:param calendar_id: 日历 ID
:param event_id: 日程 ID
:return: 日历事件的对象
:rtype: CalendarEvent
该接口用于获取指定日历下的指定日程。
https://open.feishu.cn/document/ukTMukTMukTM/ucTM14yNxUjL3ETN
"""
url = self._gen_request_url('/open-apis/calendar/v3/calendars/{}/events/{}'.format(calendar_id, event_id))
res = self._get(url, with_tenant_token=True, success_code=200000)
data = res['data']
return self._gen_calendar_event(data)
def create_calendar_event(self,
calendar_id,
summary,
start_timestamp,
end_timestamp,
description='',
attendees=None,
visibility=CalendarEventVisibility.default):
"""创建日程
:type self: OpenLark
:param calendar_id: 日历 ID
:type calendar_id: str
:param summary: 日程标题,最大长度为 256
:type summary: str
:param start_timestamp: 日程的起始时间10 位秒级时间戳
:type start_timestamp: int
:param end_timestamp: 日程的结束时间10 位秒级时间戳
:type end_timestamp: int
:param description: 日程描述,最大长度为 256默认空
:type description: str
:param attendees: 日程参与者信息,默认空数组,每个 Attendess 必须有 open_id 或者 employee_id
:type attendees: List[CalendarAttendee]
:param visibility: 公开范围
:type visibility: CalendarEventVisibility
:return: 日历事件的对象
:rtype: CalendarEvent
该接口用于在日历中创建一个日程。
https://open.feishu.cn/document/ukTMukTMukTM/ugTM14COxUjL4ETN
"""
url = self._gen_request_url('/open-apis/calendar/v3/calendars/{}/events'.format(calendar_id))
if not attendees:
attendees = []
else:
attendees = [dict(filter(lambda x: x[1], [('open_id', i.open_id),
('employee_id', i.employee_id),
('display_name', i.display_name)])) for i in attendees]
body = {
'summary': summary,
'description': description,
'start': {
'time_stamp': start_timestamp,
},
'end': {
'time_stamp': end_timestamp,
},
'attendees': attendees, # type: ignore
'visibility': visibility.value if isinstance(visibility, CalendarEventVisibility) else visibility,
}
res = self._post(url, body, with_tenant_token=True, success_code=200000)
data = res['data']
return self._gen_calendar_event(data)
def get_calendar_event_list(self,
calendar_id,
max_results=500,
page_token='',
sync_token=''):
"""获取日程列表
:type self: OpenLark
:param calendar_id: 日历 ID
:type calendar_id: str
:param max_results: 一次请求要求返回最大数,该参数不能大于 1000默认 500
:param page_token: 用于标志当次请求从哪页开始
:type page_token: str
:param sync_token: 表示从上次返回的截止页起,返回结果
:type sync_token: str
:return: page_token, sync_token 和 日历事件的列表
:rtype: Tuple[str, str, List[CalendarEvent]]
该接口用于获取指定日历下的日程列表。
https://open.feishu.cn/document/ukTMukTMukTM/ukTM14SOxUjL5ETN
"""
if max_results > 1000:
max_results = 1000
url = self._gen_request_url(
'/open-apis/calendar/v3/calendars/{}/events?max_results={}'.format(calendar_id, max_results))
if page_token:
url = '{}&page_token={}'.format(url, page_token)
if sync_token:
url = '{}&sync_token={}'.format(url, sync_token)
res = self._get(url, with_tenant_token=True, success_code=200000)
data = res.get('data', [])
page_token = res.get('page_token', '')
sync_token = res.get('sync_token', '')
calendar_event_list = [self._gen_calendar_event(i) for i in data]
return page_token, sync_token, calendar_event_list
def delete_calendar_event(self, calendar_id, event_id=''):
"""删除日程
:type self: OpenLark
:param calendar_id: 日历 ID
:param event_id: 日程 ID
该接口用于删除指定日历下的日程。
https://open.feishu.cn/document/ukTMukTMukTM/uAjM14CMyUjLwITN
"""
url = self._gen_request_url('/open-apis/calendar/v3/calendars/{}/events/{}'.format(calendar_id, event_id))
self._delete(url, with_tenant_token=True, success_code=200000)
def update_calendar_event(self,
calendar_id,
event_id,
summary=None,
start_timestamp=None,
end_timestamp=None,
description=None,
attendees=None,
visibility=None):
"""更新日程
:type self: OpenLark
:param calendar_id: 日历 ID
:type calendar_id: str
:param event_id: 日程 ID
:type event_id: str
:param summary: 日程标题,最大长度为 256
:type summary: str
:param start_timestamp: 日程的起始时间10 位秒级时间戳
:type start_timestamp: int
:param end_timestamp: 日程的结束时间10 位秒级时间戳
:type end_timestamp: int
:param description: 日程描述,最大长度为 256默认空
:type description: str
:param attendees: 日程参与者信息,默认空数组,每个 Attendess 必须有 open_id 或者 employee_id
:type attendees: List[CalendarAttendee]
:param visibility: 公开范围
:type visibility: CalendarEventVisibility
:return: 日历事件
:rtype: CalendarEvent
该接口用于在日历中创建一个日程。
https://open.feishu.cn/document/ukTMukTMukTM/uEjM14SMyUjLxITN
"""
url = self._gen_request_url('/open-apis/calendar/v3/calendars/{}/events/{}'.format(calendar_id, event_id))
if not attendees:
attendees = []
else:
attendees = [dict(filter(lambda x: x[1], [('open_id', i.open_id),
('employee_id', i.employee_id),
('display_name', i.display_name)])) for i in attendees]
body = {} # type: Dict[string_types, Any]
if summary is not None:
body['summary'] = summary
if description is not None:
body['description'] = description
if start_timestamp is not None:
body['start'] = {'time_stamp': start_timestamp}
if end_timestamp is not None:
body['end'] = {'time_stamp': end_timestamp}
if attendees is not None:
body['attendees'] = attendees
if visibility is not None:
body['visibility'] = visibility.value if isinstance(visibility, CalendarEventVisibility) else visibility
res = self._patch(url, body, with_tenant_token=True, success_code=200000)
data = res['data']
return self._gen_calendar_event(data)
# TODO:
# 邀请/移除日程参与者
# 获取访问控制列表
# 创建访问控制
# 删除访问控制
# 查询日历的忙闲状态