lark_api_utils.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. import json
  2. from typing import Optional
  3. import httpx
  4. from core.tools.errors import ToolProviderCredentialValidationError
  5. from extensions.ext_redis import redis_client
  6. def lark_auth(credentials):
  7. app_id = credentials.get("app_id")
  8. app_secret = credentials.get("app_secret")
  9. if not app_id or not app_secret:
  10. raise ToolProviderCredentialValidationError("app_id and app_secret is required")
  11. try:
  12. assert LarkRequest(app_id, app_secret).tenant_access_token is not None
  13. except Exception as e:
  14. raise ToolProviderCredentialValidationError(str(e))
  15. class LarkRequest:
  16. API_BASE_URL = "https://lark-plugin-api.solutionsuite.ai/lark-plugin"
  17. def __init__(self, app_id: str, app_secret: str):
  18. self.app_id = app_id
  19. self.app_secret = app_secret
  20. def convert_add_records(self, json_str):
  21. try:
  22. data = json.loads(json_str)
  23. if not isinstance(data, list):
  24. raise ValueError("Parsed data must be a list")
  25. converted_data = [{"fields": json.dumps(item, ensure_ascii=False)} for item in data]
  26. return converted_data
  27. except json.JSONDecodeError:
  28. raise ValueError("The input string is not valid JSON")
  29. except Exception as e:
  30. raise ValueError(f"An error occurred while processing the data: {e}")
  31. def convert_update_records(self, json_str):
  32. try:
  33. data = json.loads(json_str)
  34. if not isinstance(data, list):
  35. raise ValueError("Parsed data must be a list")
  36. converted_data = [
  37. {"fields": json.dumps(record["fields"], ensure_ascii=False), "record_id": record["record_id"]}
  38. for record in data
  39. if "fields" in record and "record_id" in record
  40. ]
  41. if len(converted_data) != len(data):
  42. raise ValueError("Each record must contain 'fields' and 'record_id'")
  43. return converted_data
  44. except json.JSONDecodeError:
  45. raise ValueError("The input string is not valid JSON")
  46. except Exception as e:
  47. raise ValueError(f"An error occurred while processing the data: {e}")
  48. @property
  49. def tenant_access_token(self) -> str:
  50. feishu_tenant_access_token = f"tools:{self.app_id}:feishu_tenant_access_token"
  51. if redis_client.exists(feishu_tenant_access_token):
  52. return redis_client.get(feishu_tenant_access_token).decode()
  53. res = self.get_tenant_access_token(self.app_id, self.app_secret)
  54. redis_client.setex(feishu_tenant_access_token, res.get("expire"), res.get("tenant_access_token"))
  55. if "tenant_access_token" in res:
  56. return res.get("tenant_access_token")
  57. return ""
  58. def _send_request(
  59. self,
  60. url: str,
  61. method: str = "post",
  62. require_token: bool = True,
  63. payload: Optional[dict] = None,
  64. params: Optional[dict] = None,
  65. ):
  66. headers = {
  67. "Content-Type": "application/json",
  68. "user-agent": "Dify",
  69. }
  70. if require_token:
  71. headers["tenant-access-token"] = f"{self.tenant_access_token}"
  72. res = httpx.request(method=method, url=url, headers=headers, json=payload, params=params, timeout=30).json()
  73. if res.get("code") != 0:
  74. raise Exception(res)
  75. return res
  76. def get_tenant_access_token(self, app_id: str, app_secret: str) -> dict:
  77. url = f"{self.API_BASE_URL}/access_token/get_tenant_access_token"
  78. payload = {"app_id": app_id, "app_secret": app_secret}
  79. res = self._send_request(url, require_token=False, payload=payload)
  80. return res
  81. def create_document(self, title: str, content: str, folder_token: str) -> dict:
  82. url = f"{self.API_BASE_URL}/document/create_document"
  83. payload = {
  84. "title": title,
  85. "content": content,
  86. "folder_token": folder_token,
  87. }
  88. res = self._send_request(url, payload=payload)
  89. if "data" in res:
  90. return res.get("data")
  91. return res
  92. def write_document(self, document_id: str, content: str, position: str = "end") -> dict:
  93. url = f"{self.API_BASE_URL}/document/write_document"
  94. payload = {"document_id": document_id, "content": content, "position": position}
  95. res = self._send_request(url, payload=payload)
  96. return res
  97. def get_document_content(self, document_id: str, mode: str = "markdown", lang: str = "0") -> str | dict:
  98. params = {
  99. "document_id": document_id,
  100. "mode": mode,
  101. "lang": lang,
  102. }
  103. url = f"{self.API_BASE_URL}/document/get_document_content"
  104. res = self._send_request(url, method="GET", params=params)
  105. if "data" in res:
  106. return res.get("data").get("content")
  107. return ""
  108. def list_document_blocks(
  109. self, document_id: str, page_token: str, user_id_type: str = "open_id", page_size: int = 500
  110. ) -> dict:
  111. params = {
  112. "user_id_type": user_id_type,
  113. "document_id": document_id,
  114. "page_size": page_size,
  115. "page_token": page_token,
  116. }
  117. url = f"{self.API_BASE_URL}/document/list_document_blocks"
  118. res = self._send_request(url, method="GET", params=params)
  119. if "data" in res:
  120. return res.get("data")
  121. return res
  122. def send_bot_message(self, receive_id_type: str, receive_id: str, msg_type: str, content: str) -> dict:
  123. url = f"{self.API_BASE_URL}/message/send_bot_message"
  124. params = {
  125. "receive_id_type": receive_id_type,
  126. }
  127. payload = {
  128. "receive_id": receive_id,
  129. "msg_type": msg_type,
  130. "content": content.strip('"').replace(r"\"", '"').replace(r"\\", "\\"),
  131. }
  132. res = self._send_request(url, params=params, payload=payload)
  133. if "data" in res:
  134. return res.get("data")
  135. return res
  136. def send_webhook_message(self, webhook: str, msg_type: str, content: str) -> dict:
  137. url = f"{self.API_BASE_URL}/message/send_webhook_message"
  138. payload = {
  139. "webhook": webhook,
  140. "msg_type": msg_type,
  141. "content": content.strip('"').replace(r"\"", '"').replace(r"\\", "\\"),
  142. }
  143. res = self._send_request(url, require_token=False, payload=payload)
  144. return res
  145. def get_chat_messages(
  146. self,
  147. container_id: str,
  148. start_time: str,
  149. end_time: str,
  150. page_token: str,
  151. sort_type: str = "ByCreateTimeAsc",
  152. page_size: int = 20,
  153. ) -> dict:
  154. url = f"{self.API_BASE_URL}/message/get_chat_messages"
  155. params = {
  156. "container_id": container_id,
  157. "start_time": start_time,
  158. "end_time": end_time,
  159. "sort_type": sort_type,
  160. "page_token": page_token,
  161. "page_size": page_size,
  162. }
  163. res = self._send_request(url, method="GET", params=params)
  164. if "data" in res:
  165. return res.get("data")
  166. return res
  167. def get_thread_messages(
  168. self, container_id: str, page_token: str, sort_type: str = "ByCreateTimeAsc", page_size: int = 20
  169. ) -> dict:
  170. url = f"{self.API_BASE_URL}/message/get_thread_messages"
  171. params = {
  172. "container_id": container_id,
  173. "sort_type": sort_type,
  174. "page_token": page_token,
  175. "page_size": page_size,
  176. }
  177. res = self._send_request(url, method="GET", params=params)
  178. if "data" in res:
  179. return res.get("data")
  180. return res
  181. def create_task(self, summary: str, start_time: str, end_time: str, completed_time: str, description: str) -> dict:
  182. url = f"{self.API_BASE_URL}/task/create_task"
  183. payload = {
  184. "summary": summary,
  185. "start_time": start_time,
  186. "end_time": end_time,
  187. "completed_at": completed_time,
  188. "description": description,
  189. }
  190. res = self._send_request(url, payload=payload)
  191. if "data" in res:
  192. return res.get("data")
  193. return res
  194. def update_task(
  195. self, task_guid: str, summary: str, start_time: str, end_time: str, completed_time: str, description: str
  196. ) -> dict:
  197. url = f"{self.API_BASE_URL}/task/update_task"
  198. payload = {
  199. "task_guid": task_guid,
  200. "summary": summary,
  201. "start_time": start_time,
  202. "end_time": end_time,
  203. "completed_time": completed_time,
  204. "description": description,
  205. }
  206. res = self._send_request(url, method="PATCH", payload=payload)
  207. if "data" in res:
  208. return res.get("data")
  209. return res
  210. def delete_task(self, task_guid: str) -> dict:
  211. url = f"{self.API_BASE_URL}/task/delete_task"
  212. payload = {
  213. "task_guid": task_guid,
  214. }
  215. res = self._send_request(url, method="DELETE", payload=payload)
  216. if "data" in res:
  217. return res.get("data")
  218. return res
  219. def add_members(self, task_guid: str, member_phone_or_email: str, member_role: str) -> dict:
  220. url = f"{self.API_BASE_URL}/task/add_members"
  221. payload = {
  222. "task_guid": task_guid,
  223. "member_phone_or_email": member_phone_or_email,
  224. "member_role": member_role,
  225. }
  226. res = self._send_request(url, payload=payload)
  227. if "data" in res:
  228. return res.get("data")
  229. return res
  230. def get_wiki_nodes(self, space_id: str, parent_node_token: str, page_token: str, page_size: int = 20) -> dict:
  231. url = f"{self.API_BASE_URL}/wiki/get_wiki_nodes"
  232. payload = {
  233. "space_id": space_id,
  234. "parent_node_token": parent_node_token,
  235. "page_token": page_token,
  236. "page_size": page_size,
  237. }
  238. res = self._send_request(url, payload=payload)
  239. if "data" in res:
  240. return res.get("data")
  241. return res
  242. def get_primary_calendar(self, user_id_type: str = "open_id") -> dict:
  243. url = f"{self.API_BASE_URL}/calendar/get_primary_calendar"
  244. params = {
  245. "user_id_type": user_id_type,
  246. }
  247. res = self._send_request(url, method="GET", params=params)
  248. if "data" in res:
  249. return res.get("data")
  250. return res
  251. def create_event(
  252. self,
  253. summary: str,
  254. description: str,
  255. start_time: str,
  256. end_time: str,
  257. attendee_ability: str,
  258. need_notification: bool = True,
  259. auto_record: bool = False,
  260. ) -> dict:
  261. url = f"{self.API_BASE_URL}/calendar/create_event"
  262. payload = {
  263. "summary": summary,
  264. "description": description,
  265. "need_notification": need_notification,
  266. "start_time": start_time,
  267. "end_time": end_time,
  268. "auto_record": auto_record,
  269. "attendee_ability": attendee_ability,
  270. }
  271. res = self._send_request(url, payload=payload)
  272. if "data" in res:
  273. return res.get("data")
  274. return res
  275. def update_event(
  276. self,
  277. event_id: str,
  278. summary: str,
  279. description: str,
  280. need_notification: bool,
  281. start_time: str,
  282. end_time: str,
  283. auto_record: bool,
  284. ) -> dict:
  285. url = f"{self.API_BASE_URL}/calendar/update_event/{event_id}"
  286. payload = {}
  287. if summary:
  288. payload["summary"] = summary
  289. if description:
  290. payload["description"] = description
  291. if start_time:
  292. payload["start_time"] = start_time
  293. if end_time:
  294. payload["end_time"] = end_time
  295. if need_notification:
  296. payload["need_notification"] = need_notification
  297. if auto_record:
  298. payload["auto_record"] = auto_record
  299. res = self._send_request(url, method="PATCH", payload=payload)
  300. return res
  301. def delete_event(self, event_id: str, need_notification: bool = True) -> dict:
  302. url = f"{self.API_BASE_URL}/calendar/delete_event/{event_id}"
  303. params = {
  304. "need_notification": need_notification,
  305. }
  306. res = self._send_request(url, method="DELETE", params=params)
  307. return res
  308. def list_events(self, start_time: str, end_time: str, page_token: str, page_size: int = 50) -> dict:
  309. url = f"{self.API_BASE_URL}/calendar/list_events"
  310. params = {
  311. "start_time": start_time,
  312. "end_time": end_time,
  313. "page_token": page_token,
  314. "page_size": page_size,
  315. }
  316. res = self._send_request(url, method="GET", params=params)
  317. if "data" in res:
  318. return res.get("data")
  319. return res
  320. def search_events(
  321. self,
  322. query: str,
  323. start_time: str,
  324. end_time: str,
  325. page_token: str,
  326. user_id_type: str = "open_id",
  327. page_size: int = 20,
  328. ) -> dict:
  329. url = f"{self.API_BASE_URL}/calendar/search_events"
  330. payload = {
  331. "query": query,
  332. "start_time": start_time,
  333. "end_time": end_time,
  334. "page_token": page_token,
  335. "user_id_type": user_id_type,
  336. "page_size": page_size,
  337. }
  338. res = self._send_request(url, payload=payload)
  339. if "data" in res:
  340. return res.get("data")
  341. return res
  342. def add_event_attendees(self, event_id: str, attendee_phone_or_email: str, need_notification: bool = True) -> dict:
  343. url = f"{self.API_BASE_URL}/calendar/add_event_attendees"
  344. payload = {
  345. "event_id": event_id,
  346. "attendee_phone_or_email": attendee_phone_or_email,
  347. "need_notification": need_notification,
  348. }
  349. res = self._send_request(url, payload=payload)
  350. if "data" in res:
  351. return res.get("data")
  352. return res
  353. def create_spreadsheet(
  354. self,
  355. title: str,
  356. folder_token: str,
  357. ) -> dict:
  358. url = f"{self.API_BASE_URL}/spreadsheet/create_spreadsheet"
  359. payload = {
  360. "title": title,
  361. "folder_token": folder_token,
  362. }
  363. res = self._send_request(url, payload=payload)
  364. if "data" in res:
  365. return res.get("data")
  366. return res
  367. def get_spreadsheet(
  368. self,
  369. spreadsheet_token: str,
  370. user_id_type: str = "open_id",
  371. ) -> dict:
  372. url = f"{self.API_BASE_URL}/spreadsheet/get_spreadsheet"
  373. params = {
  374. "spreadsheet_token": spreadsheet_token,
  375. "user_id_type": user_id_type,
  376. }
  377. res = self._send_request(url, method="GET", params=params)
  378. if "data" in res:
  379. return res.get("data")
  380. return res
  381. def list_spreadsheet_sheets(
  382. self,
  383. spreadsheet_token: str,
  384. ) -> dict:
  385. url = f"{self.API_BASE_URL}/spreadsheet/list_spreadsheet_sheets"
  386. params = {
  387. "spreadsheet_token": spreadsheet_token,
  388. }
  389. res = self._send_request(url, method="GET", params=params)
  390. if "data" in res:
  391. return res.get("data")
  392. return res
  393. def add_rows(
  394. self,
  395. spreadsheet_token: str,
  396. sheet_id: str,
  397. sheet_name: str,
  398. length: int,
  399. values: str,
  400. ) -> dict:
  401. url = f"{self.API_BASE_URL}/spreadsheet/add_rows"
  402. payload = {
  403. "spreadsheet_token": spreadsheet_token,
  404. "sheet_id": sheet_id,
  405. "sheet_name": sheet_name,
  406. "length": length,
  407. "values": values,
  408. }
  409. res = self._send_request(url, payload=payload)
  410. if "data" in res:
  411. return res.get("data")
  412. return res
  413. def add_cols(
  414. self,
  415. spreadsheet_token: str,
  416. sheet_id: str,
  417. sheet_name: str,
  418. length: int,
  419. values: str,
  420. ) -> dict:
  421. url = f"{self.API_BASE_URL}/spreadsheet/add_cols"
  422. payload = {
  423. "spreadsheet_token": spreadsheet_token,
  424. "sheet_id": sheet_id,
  425. "sheet_name": sheet_name,
  426. "length": length,
  427. "values": values,
  428. }
  429. res = self._send_request(url, payload=payload)
  430. if "data" in res:
  431. return res.get("data")
  432. return res
  433. def read_rows(
  434. self,
  435. spreadsheet_token: str,
  436. sheet_id: str,
  437. sheet_name: str,
  438. start_row: int,
  439. num_rows: int,
  440. user_id_type: str = "open_id",
  441. ) -> dict:
  442. url = f"{self.API_BASE_URL}/spreadsheet/read_rows"
  443. params = {
  444. "spreadsheet_token": spreadsheet_token,
  445. "sheet_id": sheet_id,
  446. "sheet_name": sheet_name,
  447. "start_row": start_row,
  448. "num_rows": num_rows,
  449. "user_id_type": user_id_type,
  450. }
  451. res = self._send_request(url, method="GET", params=params)
  452. if "data" in res:
  453. return res.get("data")
  454. return res
  455. def read_cols(
  456. self,
  457. spreadsheet_token: str,
  458. sheet_id: str,
  459. sheet_name: str,
  460. start_col: int,
  461. num_cols: int,
  462. user_id_type: str = "open_id",
  463. ) -> dict:
  464. url = f"{self.API_BASE_URL}/spreadsheet/read_cols"
  465. params = {
  466. "spreadsheet_token": spreadsheet_token,
  467. "sheet_id": sheet_id,
  468. "sheet_name": sheet_name,
  469. "start_col": start_col,
  470. "num_cols": num_cols,
  471. "user_id_type": user_id_type,
  472. }
  473. res = self._send_request(url, method="GET", params=params)
  474. if "data" in res:
  475. return res.get("data")
  476. return res
  477. def read_table(
  478. self,
  479. spreadsheet_token: str,
  480. sheet_id: str,
  481. sheet_name: str,
  482. num_range: str,
  483. query: str,
  484. user_id_type: str = "open_id",
  485. ) -> dict:
  486. url = f"{self.API_BASE_URL}/spreadsheet/read_table"
  487. params = {
  488. "spreadsheet_token": spreadsheet_token,
  489. "sheet_id": sheet_id,
  490. "sheet_name": sheet_name,
  491. "range": num_range,
  492. "query": query,
  493. "user_id_type": user_id_type,
  494. }
  495. res = self._send_request(url, method="GET", params=params)
  496. if "data" in res:
  497. return res.get("data")
  498. return res
  499. def create_base(
  500. self,
  501. name: str,
  502. folder_token: str,
  503. ) -> dict:
  504. url = f"{self.API_BASE_URL}/base/create_base"
  505. payload = {
  506. "name": name,
  507. "folder_token": folder_token,
  508. }
  509. res = self._send_request(url, payload=payload)
  510. if "data" in res:
  511. return res.get("data")
  512. return res
  513. def add_records(
  514. self,
  515. app_token: str,
  516. table_id: str,
  517. table_name: str,
  518. records: str,
  519. user_id_type: str = "open_id",
  520. ) -> dict:
  521. url = f"{self.API_BASE_URL}/base/add_records"
  522. params = {
  523. "app_token": app_token,
  524. "table_id": table_id,
  525. "table_name": table_name,
  526. "user_id_type": user_id_type,
  527. }
  528. payload = {
  529. "records": self.convert_add_records(records),
  530. }
  531. res = self._send_request(url, params=params, payload=payload)
  532. if "data" in res:
  533. return res.get("data")
  534. return res
  535. def update_records(
  536. self,
  537. app_token: str,
  538. table_id: str,
  539. table_name: str,
  540. records: str,
  541. user_id_type: str,
  542. ) -> dict:
  543. url = f"{self.API_BASE_URL}/base/update_records"
  544. params = {
  545. "app_token": app_token,
  546. "table_id": table_id,
  547. "table_name": table_name,
  548. "user_id_type": user_id_type,
  549. }
  550. payload = {
  551. "records": self.convert_update_records(records),
  552. }
  553. res = self._send_request(url, params=params, payload=payload)
  554. if "data" in res:
  555. return res.get("data")
  556. return res
  557. def delete_records(
  558. self,
  559. app_token: str,
  560. table_id: str,
  561. table_name: str,
  562. record_ids: str,
  563. ) -> dict:
  564. url = f"{self.API_BASE_URL}/base/delete_records"
  565. params = {
  566. "app_token": app_token,
  567. "table_id": table_id,
  568. "table_name": table_name,
  569. }
  570. if not record_ids:
  571. record_id_list = []
  572. else:
  573. try:
  574. record_id_list = json.loads(record_ids)
  575. except json.JSONDecodeError:
  576. raise ValueError("The input string is not valid JSON")
  577. payload = {
  578. "records": record_id_list,
  579. }
  580. res = self._send_request(url, params=params, payload=payload)
  581. if "data" in res:
  582. return res.get("data")
  583. return res
  584. def search_record(
  585. self,
  586. app_token: str,
  587. table_id: str,
  588. table_name: str,
  589. view_id: str,
  590. field_names: str,
  591. sort: str,
  592. filters: str,
  593. page_token: str,
  594. automatic_fields: bool = False,
  595. user_id_type: str = "open_id",
  596. page_size: int = 20,
  597. ) -> dict:
  598. url = f"{self.API_BASE_URL}/base/search_record"
  599. params = {
  600. "app_token": app_token,
  601. "table_id": table_id,
  602. "table_name": table_name,
  603. "user_id_type": user_id_type,
  604. "page_token": page_token,
  605. "page_size": page_size,
  606. }
  607. if not field_names:
  608. field_name_list = []
  609. else:
  610. try:
  611. field_name_list = json.loads(field_names)
  612. except json.JSONDecodeError:
  613. raise ValueError("The input string is not valid JSON")
  614. if not sort:
  615. sort_list = []
  616. else:
  617. try:
  618. sort_list = json.loads(sort)
  619. except json.JSONDecodeError:
  620. raise ValueError("The input string is not valid JSON")
  621. if not filters:
  622. filter_dict = {}
  623. else:
  624. try:
  625. filter_dict = json.loads(filters)
  626. except json.JSONDecodeError:
  627. raise ValueError("The input string is not valid JSON")
  628. payload = {}
  629. if view_id:
  630. payload["view_id"] = view_id
  631. if field_names:
  632. payload["field_names"] = field_name_list
  633. if sort:
  634. payload["sort"] = sort_list
  635. if filters:
  636. payload["filter"] = filter_dict
  637. if automatic_fields:
  638. payload["automatic_fields"] = automatic_fields
  639. res = self._send_request(url, params=params, payload=payload)
  640. if "data" in res:
  641. return res.get("data")
  642. return res
  643. def get_base_info(
  644. self,
  645. app_token: str,
  646. ) -> dict:
  647. url = f"{self.API_BASE_URL}/base/get_base_info"
  648. params = {
  649. "app_token": app_token,
  650. }
  651. res = self._send_request(url, method="GET", params=params)
  652. if "data" in res:
  653. return res.get("data")
  654. return res
  655. def create_table(
  656. self,
  657. app_token: str,
  658. table_name: str,
  659. default_view_name: str,
  660. fields: str,
  661. ) -> dict:
  662. url = f"{self.API_BASE_URL}/base/create_table"
  663. params = {
  664. "app_token": app_token,
  665. }
  666. if not fields:
  667. fields_list = []
  668. else:
  669. try:
  670. fields_list = json.loads(fields)
  671. except json.JSONDecodeError:
  672. raise ValueError("The input string is not valid JSON")
  673. payload = {
  674. "name": table_name,
  675. "fields": fields_list,
  676. }
  677. if default_view_name:
  678. payload["default_view_name"] = default_view_name
  679. res = self._send_request(url, params=params, payload=payload)
  680. if "data" in res:
  681. return res.get("data")
  682. return res
  683. def delete_tables(
  684. self,
  685. app_token: str,
  686. table_ids: str,
  687. table_names: str,
  688. ) -> dict:
  689. url = f"{self.API_BASE_URL}/base/delete_tables"
  690. params = {
  691. "app_token": app_token,
  692. }
  693. if not table_ids:
  694. table_id_list = []
  695. else:
  696. try:
  697. table_id_list = json.loads(table_ids)
  698. except json.JSONDecodeError:
  699. raise ValueError("The input string is not valid JSON")
  700. if not table_names:
  701. table_name_list = []
  702. else:
  703. try:
  704. table_name_list = json.loads(table_names)
  705. except json.JSONDecodeError:
  706. raise ValueError("The input string is not valid JSON")
  707. payload = {
  708. "table_ids": table_id_list,
  709. "table_names": table_name_list,
  710. }
  711. res = self._send_request(url, params=params, payload=payload)
  712. if "data" in res:
  713. return res.get("data")
  714. return res
  715. def list_tables(
  716. self,
  717. app_token: str,
  718. page_token: str,
  719. page_size: int = 20,
  720. ) -> dict:
  721. url = f"{self.API_BASE_URL}/base/list_tables"
  722. params = {
  723. "app_token": app_token,
  724. "page_token": page_token,
  725. "page_size": page_size,
  726. }
  727. res = self._send_request(url, method="GET", params=params)
  728. if "data" in res:
  729. return res.get("data")
  730. return res
  731. def read_records(
  732. self,
  733. app_token: str,
  734. table_id: str,
  735. table_name: str,
  736. record_ids: str,
  737. user_id_type: str = "open_id",
  738. ) -> dict:
  739. url = f"{self.API_BASE_URL}/base/read_records"
  740. params = {
  741. "app_token": app_token,
  742. "table_id": table_id,
  743. "table_name": table_name,
  744. }
  745. if not record_ids:
  746. record_id_list = []
  747. else:
  748. try:
  749. record_id_list = json.loads(record_ids)
  750. except json.JSONDecodeError:
  751. raise ValueError("The input string is not valid JSON")
  752. payload = {
  753. "record_ids": record_id_list,
  754. "user_id_type": user_id_type,
  755. }
  756. res = self._send_request(url, method="POST", params=params, payload=payload)
  757. if "data" in res:
  758. return res.get("data")
  759. return res