async_feishu_api.py 7.6 KB

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