221 lines
6.7 KiB
Python
221 lines
6.7 KiB
Python
import requests
|
|
import time
|
|
|
|
|
|
def transform_data(data, mapping):
|
|
temp = {}
|
|
for k, v in mapping.items():
|
|
if k in data:
|
|
if k == "date":
|
|
timestamp = str(int(time.mktime(time.strptime(data[k], "%Y-%m-%d %H:%M:%S"))))
|
|
temp[v] = timestamp + "000"
|
|
else:
|
|
temp[v] = data[k]
|
|
return temp
|
|
|
|
|
|
class SmartSheet:
|
|
def __init__(self, doc_id, sheet_id):
|
|
self.doc_id = doc_id
|
|
self.sheet_id = sheet_id
|
|
self._columns = None
|
|
self._data = None
|
|
|
|
@staticmethod
|
|
def _post(url, body):
|
|
resp = requests.post(url, json=body)
|
|
if resp.status_code == 200:
|
|
return resp.json()
|
|
return {}
|
|
|
|
def _get_columns(self):
|
|
url = "https://a.cmdp.cn/umss/v1/wxw/common/submit"
|
|
body = {
|
|
"url": "https://qyapi.weixin.qq.com/cgi-bin/wedoc/smartsheet/get_fields",
|
|
"method": "POST",
|
|
"body": {
|
|
"docid": self.doc_id,
|
|
"sheet_id": self.sheet_id
|
|
}
|
|
}
|
|
response = self._post(url, body)
|
|
if response:
|
|
fields = response["fields"]
|
|
return fields
|
|
return []
|
|
|
|
def _get_data(self, filters: dict, cursor: int = 0, limit: int = 1000):
|
|
url = "https://a.cmdp.cn/umss/v1/wxw/smartSheet/getRecords"
|
|
body = {
|
|
"docid": self.doc_id,
|
|
"sheet_id": self.sheet_id,
|
|
"filter_spec": filters,
|
|
"offset": cursor,
|
|
"limit": limit
|
|
}
|
|
response = self._post(url, body)
|
|
if response:
|
|
cursor = response["next"]
|
|
records = response["records"]
|
|
return cursor, records
|
|
return 0, []
|
|
|
|
def _add(self, records: list):
|
|
url = "https://a.cmdp.cn/umss/v1/wxw/smartSheet/addRecords"
|
|
body = {
|
|
"docid": self.doc_id,
|
|
"sheet_id": self.sheet_id,
|
|
"key_type": "CELL_VALUE_KEY_TYPE_FIELD_TITLE",
|
|
"records": records
|
|
}
|
|
response = self._post(url, body)
|
|
if response:
|
|
return True
|
|
return False
|
|
|
|
def _transform_data(self, data: dict):
|
|
result = {}
|
|
columns = self.columns
|
|
for i in data:
|
|
type_info = columns[i]
|
|
i_type = type_info.get("field_type")
|
|
if i_type == "FIELD_TYPE_TEXT":
|
|
result[i] = [
|
|
{
|
|
"text": data[i],
|
|
"type": "text"
|
|
}
|
|
]
|
|
elif i_type == "FIELD_TYPE_SINGLE_SELECT":
|
|
options = {i["text"]: i for i in type_info['property_single_select']["options"]}
|
|
result[i] = [
|
|
options[data[i]]
|
|
]
|
|
else:
|
|
result[i] = data[i]
|
|
return result
|
|
|
|
def _convert_data(self, data: dict):
|
|
va = {}
|
|
for v in data:
|
|
type_info = self.columns[v]
|
|
i_type = type_info.get("field_type")
|
|
if i_type == "FIELD_TYPE_TEXT":
|
|
va[v] = "".join([m["text"] for m in data[v]])
|
|
elif i_type == "FIELD_TYPE_DATE_TIME":
|
|
va[v] = 0 if data[v] is None else data[v]
|
|
elif i_type == "FIELD_TYPE_NUMBER":
|
|
va[v] = 0 if data[v] is None else data[v]
|
|
elif i_type == "FIELD_TYPE_SELECT":
|
|
va[v] = [m["text"] for m in data[v]]
|
|
elif i_type == "FIELD_TYPE_SINGLE_SELECT":
|
|
va[v] = data[v][0]["text"] if data[v] else ""
|
|
elif i_type == "FIELD_TYPE_TWOWAYLINKRECORDS":
|
|
va[v] = data[v]
|
|
else:
|
|
print(i_type, data[v],type_info)
|
|
return va
|
|
|
|
@property
|
|
def columns(self):
|
|
if self._columns is None:
|
|
self._columns = self._get_columns()
|
|
return {i["field_title"]: i for i in self._columns}
|
|
|
|
@property
|
|
def data(self):
|
|
if self._data is None:
|
|
self._data = self.search({})
|
|
return self._data
|
|
|
|
def search(self, filters: dict):
|
|
cursor = 0
|
|
result = []
|
|
while True:
|
|
cursor, records = self._get_data(filters, cursor=cursor)
|
|
result += records
|
|
if cursor == 0:
|
|
break
|
|
return result
|
|
|
|
def add(self, data: dict):
|
|
return self._add([{"values": self._transform_data(data)}])
|
|
|
|
def batch_add(self, data_list: list):
|
|
return self._add([{"values": self._transform_data(i)} for i in data_list])
|
|
|
|
def to_json(self):
|
|
data = []
|
|
for i in self.data:
|
|
values = i["values"]
|
|
va = self._convert_data(values)
|
|
va['_rid'] = i["record_id"]
|
|
data.append(va)
|
|
return {"columns": self.columns, "data": data}
|
|
|
|
|
|
class SmartTableApi:
|
|
def __init__(self, doc_id):
|
|
self.doc_id = doc_id
|
|
self.metadata_id = None
|
|
self._metadata = None
|
|
self.metadata_table = None
|
|
self._get_sheet_list()
|
|
|
|
@staticmethod
|
|
def _post(url, body):
|
|
resp = requests.post(url, json=body)
|
|
if resp.status_code == 200:
|
|
return resp.json()
|
|
return {}
|
|
|
|
def _get_sheet_list(self):
|
|
url = "https://a.cmdp.cn/umss/v1/wxw/common/submit"
|
|
body = {
|
|
"url": "https://qyapi.weixin.qq.com/cgi-bin/wedoc/smartsheet/get_sheet",
|
|
"method": "POST",
|
|
"body": {
|
|
"docid": self.doc_id
|
|
|
|
}
|
|
}
|
|
resp = self._post(url, body)
|
|
sheet_list = resp.get("sheet_list", [])
|
|
result = {i["title"]: i["sheet_id"] for i in sheet_list}
|
|
self.metadata_id = result.get("Metadata")
|
|
if "Metadata" in result:
|
|
del result["Metadata"]
|
|
self._metadata = result
|
|
|
|
@property
|
|
def metadata(self):
|
|
return self._metadata
|
|
|
|
def _update_metadata(self, sheet_id, sheet_name):
|
|
if not self.metadata_table:
|
|
self.metadata_table = SmartSheet(self.doc_id, self.metadata_id)
|
|
self.metadata_table.add({"名称": sheet_name, "类型": "sheet", "值": sheet_id})
|
|
pass
|
|
|
|
def add_sheet(self, sheet_name):
|
|
url = "https://a.cmdp.cn/umss/v1/wxw/addSheet"
|
|
body = {
|
|
"docid": self.doc_id,
|
|
"properties": {
|
|
"title": sheet_name
|
|
}
|
|
}
|
|
resp = self._post(url, body)
|
|
if resp.get("properties"):
|
|
self._update_metadata(sheet_id=resp["properties"]["sheet_id"], sheet_name=sheet_name)
|
|
return resp
|
|
|
|
def get_sheet(self, sheet_id):
|
|
return SmartSheet(self.doc_id, sheet_id)
|
|
|
|
def get_sheet_by_name(self, sheet_name):
|
|
if sheet_name in self.metadata:
|
|
return self.get_sheet(self.metadata[sheet_name])
|
|
else:
|
|
return None
|