operations_project/apps/feishu/services/bitable_service.py
2025-05-20 15:57:10 +08:00

216 lines
6.8 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.

import json
import re
import requests
from urllib.parse import urljoin
# 基础URL地址
BASE_API_URL = "https://open.feishu.cn/open-apis/"
class BitableService:
"""
飞书多维表格服务类
"""
@staticmethod
def make_request(method, url, headers=None, params=None, json_data=None):
"""
发送请求到飞书API
Args:
method: 请求方法GET/POST等
url: API路径不含基础URL
headers: 请求头
params: URL参数
json_data: JSON数据体
Returns:
dict: 响应数据
"""
full_url = urljoin(BASE_API_URL, url)
if headers is None:
headers = {}
response = requests.request(
method=method,
url=full_url,
headers=headers,
params=params,
json=json_data
)
# 检查响应
if not response.ok:
error_msg = f"API 请求失败: {response.status_code}, 响应: {response.text}"
print(error_msg)
raise Exception(error_msg)
return response.json()
@staticmethod
def extract_params_from_url(table_url):
"""
从URL中提取app_token和table_id
Args:
table_url: 飞书多维表格URL
Returns:
tuple: (app_token, table_id) 元组
Raises:
ValueError: 如果无法从URL中提取必要参数
"""
app_token_match = re.search(r'base/([^?]+)', table_url)
table_id_match = re.search(r'table=([^&]+)', table_url)
if not app_token_match or not table_id_match:
raise ValueError("无法从URL中提取必要参数请确认URL格式正确")
return app_token_match.group(1), table_id_match.group(1)
@staticmethod
def get_metadata(app_token, table_id, access_token):
"""
获取多维表格元数据
Args:
app_token: 应用令牌
table_id: 表格ID
access_token: 访问令牌
Returns:
dict: 表格元数据
"""
try:
# 构造请求
url = f"bitable/v1/apps/{app_token}/tables/{table_id}"
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
# 发送请求
response = BitableService.make_request("GET", url, headers=headers)
# 检查响应
if response and "code" in response and response["code"] == 0:
return response.get("data", {}).get("table", {})
# 发生错误
error_msg = f"获取多维表格元数据失败: {json.dumps(response)}"
print(error_msg)
raise Exception(error_msg)
except Exception as e:
# 如果正常API调用失败使用替代方法
print(f"获取多维表格元数据失败: {str(e)}")
# 简单返回一个基本名称
return {
"name": f"table_{table_id}",
"description": "自动创建的表格"
}
@staticmethod
def search_records(app_token, table_id, access_token, filter_exp=None, sort=None, page_size=20, page_token=None):
"""
查询多维表格记录
Args:
app_token: 应用令牌
table_id: 表格ID
access_token: 访问令牌
filter_exp: 过滤条件
sort: 排序条件
page_size: 每页大小
page_token: 分页标记
Returns:
dict: 查询结果
Raises:
Exception: 查询失败时抛出异常
"""
try:
# 构造请求URL
url = f"bitable/v1/apps/{app_token}/tables/{table_id}/records/search"
# 请求头
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
# 查询参数
params = {"page_size": page_size}
if page_token:
params["page_token"] = page_token
# 请求体
json_data = {}
if filter_exp:
json_data["filter"] = filter_exp
if sort:
json_data["sort"] = sort
# 发送请求
response = BitableService.make_request("POST", url, headers=headers, params=params, json_data=json_data)
# 检查响应
if response and "code" in response and response["code"] == 0:
return response.get("data", {})
# 发生错误
error_msg = f"查询飞书多维表格失败: {json.dumps(response)}"
print(error_msg)
raise Exception(error_msg)
except Exception as e:
# 记录详细错误
print(f"查询飞书多维表格发生错误: {str(e)}")
raise
@staticmethod
def get_table_fields(app_token, table_id, access_token):
"""
获取多维表格的字段信息
Args:
app_token: 应用令牌
table_id: 表格ID
access_token: 访问令牌
Returns:
list: 字段信息列表
"""
try:
# 构造请求
url = f"bitable/v1/apps/{app_token}/tables/{table_id}/fields"
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
params = {"page_size": 100}
# 发送请求
response = BitableService.make_request("GET", url, headers=headers, params=params)
# 检查响应
if response and "code" in response and response["code"] == 0:
return response.get("data", {}).get("items", [])
# 发生错误
error_msg = f"获取多维表格字段失败: {json.dumps(response)}"
print(error_msg)
raise Exception(error_msg)
except Exception as e:
# 记录详细错误
print(f"获取字段信息失败: {str(e)}")
# 如果获取失败,返回一个基本字段集
return [
{"field_name": "title", "type": "text", "property": {}},
{"field_name": "description", "type": "text", "property": {}},
{"field_name": "created_time", "type": "datetime", "property": {}}
]