async_feishu_api.py 7.7 KB

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