feishu_api.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import json
  2. import requests
  3. class Feishu:
  4. # 外部服务号投流监测机器人
  5. outside_gzh_monitor_bot = "https://open.feishu.cn/open-apis/bot/v2/hook/0899d43d-9f65-48ce-a419-f83ac935bf59"
  6. # 长文 daily 报警机器人
  7. long_articles_bot = "https://open.feishu.cn/open-apis/bot/v2/hook/b44333f2-16c0-4cb1-af01-d135f8704410"
  8. # 测试环境报警机器人
  9. long_articles_bot_dev = "https://open.feishu.cn/open-apis/bot/v2/hook/f32c0456-847f-41f3-97db-33fcc1616bcd"
  10. def __init__(self):
  11. self.token = None
  12. self.headers = {"Content-Type": "application/json"}
  13. self.mention_all = {
  14. "content": "<at id=all></at>\n",
  15. "tag": "lark_md",
  16. }
  17. self.not_mention = {}
  18. def fetch_token(self):
  19. url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/"
  20. post_data = {
  21. "app_id": "cli_a51114cf8bf8d00c",
  22. "app_secret": "cNoTAqMpsAm7mPBcpCAXFfvOzCNL27fe",
  23. }
  24. response = requests.request("POST", url=url, data=post_data)
  25. tenant_access_token = response.json()["tenant_access_token"]
  26. self.token = tenant_access_token
  27. class FeishuSheetApi(Feishu):
  28. def prepend_value(self, sheet_token, sheet_id, ranges, values):
  29. insert_value_url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{}/values_prepend".format(
  30. sheet_token
  31. )
  32. headers = {
  33. "Authorization": "Bearer " + self.token,
  34. "contentType": "application/json; charset=utf-8",
  35. }
  36. body = {
  37. "valueRange": {"range": "{}!{}".format(sheet_id, ranges), "values": values}
  38. }
  39. response = requests.request(
  40. "POST", url=insert_value_url, headers=headers, json=body
  41. )
  42. print(response.json())
  43. def insert_value(self, sheet_token, sheet_id, ranges, values):
  44. insert_value_url = (
  45. "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{}/values".format(
  46. sheet_token
  47. )
  48. )
  49. headers = {
  50. "Authorization": "Bearer " + self.token,
  51. "contentType": "application/json; charset=utf-8",
  52. }
  53. body = {
  54. "valueRange": {"range": "{}!{}".format(sheet_id, ranges), "values": values}
  55. }
  56. response = requests.request(
  57. "PUT", url=insert_value_url, headers=headers, json=body
  58. )
  59. print(response.json())
  60. class FeishuBotApi(Feishu):
  61. @classmethod
  62. def create_feishu_columns_sheet(
  63. cls,
  64. sheet_type,
  65. sheet_name,
  66. display_name,
  67. width="auto",
  68. vertical_align="top",
  69. horizontal_align="left",
  70. number_format=None,
  71. ):
  72. match sheet_type:
  73. case "plain_text":
  74. return {
  75. "name": sheet_name,
  76. "display_name": display_name,
  77. "width": width,
  78. "data_type": "text",
  79. "vertical_align": vertical_align,
  80. "horizontal_align": horizontal_align,
  81. }
  82. case "lark_md":
  83. return {
  84. "name": sheet_name,
  85. "display_name": display_name,
  86. "data_type": "lark_md",
  87. }
  88. case "number":
  89. return {
  90. "name": sheet_name,
  91. "display_name": display_name,
  92. "data_type": "number",
  93. "format": number_format,
  94. "width": width,
  95. }
  96. case "date":
  97. return {
  98. "name": sheet_name,
  99. "display_name": display_name,
  100. "data_type": "date",
  101. "date_format": "YYYY/MM/DD",
  102. }
  103. case "options":
  104. return {
  105. "name": sheet_name,
  106. "display_name": display_name,
  107. "data_type": "options",
  108. }
  109. case _:
  110. return {
  111. "name": sheet_name,
  112. "display_name": display_name,
  113. "width": width,
  114. "data_type": "text",
  115. "vertical_align": vertical_align,
  116. "horizontal_align": horizontal_align,
  117. }
  118. # 表格形式
  119. def create_feishu_table(self, title, columns, rows, mention):
  120. table_base = {
  121. "header": {
  122. "template": "blue",
  123. "title": {"content": title, "tag": "plain_text"},
  124. },
  125. "elements": [
  126. self.mention_all if mention else self.not_mention,
  127. {
  128. "tag": "table",
  129. "page_size": len(rows) + 1,
  130. "row_height": "low",
  131. "header_style": {
  132. "text_align": "left",
  133. "text_size": "normal",
  134. "background_style": "grey",
  135. "text_color": "default",
  136. "bold": True,
  137. "lines": 1,
  138. },
  139. "columns": columns,
  140. "rows": rows,
  141. },
  142. ],
  143. }
  144. return table_base
  145. def create_feishu_bot_obj(self, title, mention, detail):
  146. """
  147. create feishu bot object
  148. """
  149. return {
  150. "elements": [
  151. {
  152. "tag": "div",
  153. "text": self.mention_all if mention else self.not_mention,
  154. },
  155. {
  156. "tag": "div",
  157. "text": {
  158. "content": json.dumps(detail, ensure_ascii=False, indent=4),
  159. "tag": "lark_md",
  160. },
  161. },
  162. ],
  163. "header": {"title": {"content": title, "tag": "plain_text"}},
  164. }
  165. # bot
  166. def bot(self, title, detail, mention=True, table=False, env="prod"):
  167. match env:
  168. case "dev":
  169. url = self.long_articles_bot_dev
  170. case "prod":
  171. url = self.long_articles_bot
  172. case "outside_gzh_monitor":
  173. url = self.outside_gzh_monitor_bot
  174. case _:
  175. url = self.long_articles_bot_dev
  176. headers = {"Content-Type": "application/json"}
  177. if table:
  178. card = self.create_feishu_table(
  179. title=title,
  180. columns=detail["columns"],
  181. rows=detail["rows"],
  182. mention=mention,
  183. )
  184. else:
  185. card = self.create_feishu_bot_obj(
  186. title=title, mention=mention, detail=detail
  187. )
  188. payload = {"msg_type": "interactive", "card": card}
  189. res = requests.request(
  190. "POST", url=url, headers=headers, data=json.dumps(payload), timeout=10
  191. )
  192. return res