text: # coding: utf-8
  
  from __future__ import absolute_import, division, print_function, unicode_literals
  
  from typing import TYPE_CHECKING
  
  from utils.feishu.dt_code import OAuthCodeToSessionResp, User
  from utils.feishu.dt_help import make_datatype
  
  if TYPE_CHECKING:
      from utils.feishu.api import OpenLark
  
  
  class APIOAuthMixin(object):
      def gen_oauth_url(self, state=''):
          """生成 OAuth 授权链接，请求身份验证
  
          :type self: OpenLark
          :param state: 用来维护请求和回调状态的附加字符串，在授权完成回调时会附加此参数，
                        应用可以根据此字符串来判断上下文关系
          :return: 跳转链接
          :rtype: str
  
          应用请求用户身份验证时，需按如下方式构造登录链接，并跳转至此链接。飞书客户端内用户免登，系统浏览器内用户需完成扫码登录。
  
          特别需要注意的是：老 api 获取的 expire_in 是时间戳，新 api 获取的 expire_in 是秒数
  
          https://open.feishu.cn/document/ukTMukTMukTM/ukzN4UjL5cDO14SO3gTN
          """
          url = '/open-apis/authen/v1/index?redirect_uri={}&app_id={}&state={}'
  
          return self._gen_request_url(url.format(self.oauth_redirect_uri, self.app_id, state))
  
      def oauth_code_2_session(self, code):
          """获取登录用户身份
  
          :type self: OpenLark
          :param code: 扫码登录后会自动 302 到 redirect_uri 并带上此参数
          :type code: str
          :return: OAuthCodeToSessionResp
          :rtype: OAuthCodeToSessionResp
  
          Web 扫码后拿到的 code 换取用户信息，通过此接口获取登录用户身份。
  
          特别需要注意的是：老 api 获取的 expire_in 是时间戳，新 api 获取的 expire_in 是秒数
  
          https://open.feishu.cn/document/ukTMukTMukTM/uEDO4UjLxgDO14SM4gTN
          """
          url = self._gen_request_url('/open-apis/authen/v1/access_token')
  
          body = {
              'app_access_token': self.app_access_token,
              'grant_type': 'authorization_code',
              'code': code,
          }
          res = self._post(url, body)
  
          return make_datatype(OAuthCodeToSessionResp, res.get('data') or {})
  
      def refresh_user_session(self, refresh_token):
          """刷新用户扫码登录后获取的 access_token
  
          :type self: OpenLark
          :param refresh_token: 扫码登录后会拿到这个值
          :type refresh_token: str
          :return: OAuthCodeToSessionResp
          :rtype: OAuthCodeToSessionResp
  
          刷新用户 token
  
          特别需要注意的是：老 api 获取的 expire_in 是时间戳，新 api 获取的 expire_in 是秒数
  
          https://open.feishu.cn/document/ukTMukTMukTM/uQDO4UjL0gDO14CN4gTN
          """
          url = self._gen_request_url('/open-apis/authen/v1/refresh_access_token')
  
          body = {
              "app_access_token": self.app_access_token,
              "grant_type": "refresh_token",
              "refresh_token": refresh_token
          }
          res = self._post(url, body)
  
          return make_datatype(OAuthCodeToSessionResp, res.get('data') or {})
  
      def oauth_get_user(self, user_access_token):
          """获取用户信息
  
          :type self: OpenLark
          :param user_access_token:
  
          此接口仅用于获取登录用户的信息。 调用此接口需要在 Header 中带上 user_access_token。
  
          https://open.feishu.cn/document/ukTMukTMukTM/uIDO4UjLygDO14iM4gTN
          """
          url = self._gen_request_url('/open-apis/authen/v1/user_info')
          res = self._get(url, auth_token=user_access_token)
          data = res['data']
  
          data['avatar_url'] = data.get('avatar') or data.get('avatar_url')
          data['user_id'] = data.get('user_id') or data.get('employee_id')
          return make_datatype(User, data)
  