response.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. """
  2. @author: luojunhui
  3. """
  4. import json
  5. import uuid
  6. import time
  7. import random
  8. import hashlib
  9. import urllib.parse
  10. from applications.functions.log import logging
  11. from static.config import db_article
  12. from applications.functions.common import request_for_info
  13. class Response(object):
  14. """
  15. 召回逻辑
  16. """
  17. def __init__(self, trace_id, mysql_client, mini_program_type):
  18. """
  19. 长文: 25, 29, 31
  20. 投流: 33
  21. 企微: 27
  22. :param trace_id:
  23. :param mysql_client:
  24. :param mini_program_type:
  25. """
  26. self.trace_id = trace_id
  27. self.mysql_client = mysql_client
  28. self.mini_program_type = mini_program_type
  29. self.mini_map = {
  30. # 25: {
  31. # "avatar": "https://rescdn.yishihui.com/0temp/ttmhzfsh.png",
  32. # "id": "wx0b7d95eb293b783b",
  33. # "name": "天天美好祝福生活",
  34. # "index": 25,
  35. # },
  36. 25: {
  37. "avatar": "https://rescdn.yishihui.com/0temp/pqsp.png",
  38. "id": "wxbdd2a2e93d9a6e25",
  39. "name": "票圈视频",
  40. "index": 25
  41. },
  42. 29: {
  43. "avatar": "https://rescdn.yishihui.com/0temp/cyfyld.png",
  44. "id": "wx65c76bb4c67934db",
  45. "name": "财运福运来到",
  46. "index": 29,
  47. },
  48. 31: {
  49. "avatar": "https://rescdn.yishihui.com/0temp/mhzfshxf2.png",
  50. "id": "wx2e4478b1641b3b15",
  51. "name": "美好祝福生活幸福",
  52. "index": 31,
  53. },
  54. 36: {
  55. "avatar": "https://rescdn.yishihui.com/0temp/zfyfyc.jpeg",
  56. "id": "wxcddf231abd0dabdc",
  57. "name": "祝福有福有财",
  58. "index": 36,
  59. },
  60. 27: {
  61. "avatar": "https://rescdn.yishihui.com/0temp/xymhfqdd.png",
  62. "id": "wx7187c217efef24a7",
  63. "name": "幸运美好福气多多",
  64. "index": 27,
  65. },
  66. # 33: {
  67. # "avatar": "https://rescdn.yishihui.com/0temp/ssnnfqd.jpeg",
  68. # "id": "wx5e67713277549b6f",
  69. # "name": "年年岁岁福气多",
  70. # "index": 33,
  71. # },
  72. 33: {
  73. "avatar": "https://rescdn.yishihui.com/0temp/pqsp.png",
  74. "id": "wxbdd2a2e93d9a6e25",
  75. "name": "票圈视频",
  76. "index": 33
  77. }
  78. }
  79. # self.test_id_set = {'gh_080bb43aa0dc', 'gh_e0eb490115f5', 'gh_6d9f36e3a7be', 'gh_29074b51f2b7', 'gh_6d205db62f04',
  80. # 'gh_d49df5e974ca', 'gh_d4dffc34ac39', 'gh_89ef4798d3ea', 'gh_b15de7c99912', 'gh_9eef14ad6c16',
  81. # 'gh_0c89e11f8bf3', 'gh_f902cea89e48', 'gh_6b7c2a257263', 'gh_183d80deffb8', 'gh_9f8dc5b0c74e',
  82. # 'gh_1b27dd1beeca', 'gh_e24da99dc899', 'gh_dd4c857bbb36', 'gh_7e5818b2dd83'}
  83. async def get_result(self):
  84. """
  85. 获取结果
  86. :return:
  87. """
  88. select_sql = f"""
  89. SELECT gh_id, recall_video_id1, recall_video_id2, recall_video_id3, kimi_title, content_status, process_times
  90. FROM {db_article}
  91. WHERE trace_id = '{self.trace_id}';
  92. """
  93. info_tuple = await self.mysql_client.async_select(select_sql)
  94. gh_id, vid1, vid2, vid3, kimi_title, content_status, process_times = info_tuple[
  95. 0
  96. ]
  97. response = {
  98. "gh_id": gh_id,
  99. "vid_list": [vid1, vid2, vid3],
  100. "kimi_title": kimi_title,
  101. "content_status": content_status,
  102. "process_times": process_times,
  103. }
  104. print(response)
  105. return response
  106. def create_gzh_path(self, video_id, shared_uid, gh_id):
  107. """
  108. :param gh_id: 公众号账号的gh_id
  109. :param video_id: 视频 id
  110. :param shared_uid: 分享 id
  111. """
  112. def generate_source_id():
  113. """
  114. generate_source_id
  115. :return:
  116. """
  117. timestamp = str(int(time.time() * 1000))
  118. random_str = str(random.randint(1000, 9999))
  119. hash_input = f"{timestamp}-{random_str}"
  120. return hashlib.md5(hash_input.encode()).hexdigest()
  121. root_share_id = str(uuid.uuid4())
  122. if self.mini_program_type == 2:
  123. source_id = (
  124. "touliu_tencentGzhArticle_{}_".format(gh_id) + generate_source_id()
  125. )
  126. elif self.mini_program_type == 1:
  127. source_id = "longArticles_" + generate_source_id()
  128. elif self.mini_program_type == 3:
  129. source_id = "WeCom_" + generate_source_id()
  130. else:
  131. source_id = "Error mini_program_type {}".format(self.mini_program_type)
  132. url = f"pages/user-videos?id={video_id}&su={shared_uid}&fromGzh=1&rootShareId={root_share_id}&shareId={root_share_id}&rootSourceId={source_id}"
  133. # 自动把 root_share_id 加入到白名单
  134. # auto_white(root_share_id)
  135. return (
  136. root_share_id,
  137. source_id,
  138. f"pages/category?jumpPage={urllib.parse.quote(url, safe='')}",
  139. )
  140. def choose_mini_program(self, mini_id):
  141. """
  142. 获取小程序分享卡片
  143. :return:
  144. """
  145. mini_info = self.mini_map[mini_id]
  146. return (
  147. mini_info["avatar"],
  148. mini_info["id"],
  149. mini_info["name"],
  150. mini_info["index"],
  151. )
  152. async def generate_card(self, video_id, kimi_title, index, gh_id, mini_id):
  153. """
  154. 生成分享卡片
  155. :return:
  156. """
  157. response = request_for_info(video_id)
  158. productionCover = response["data"][0]["shareImgPath"]
  159. productionName = kimi_title
  160. videoUrl = response["data"][0]["videoPath"]
  161. user_id = response["data"][0]["user"]["uid"]
  162. programAvatar, programId, programName, pqMiniId = self.choose_mini_program(
  163. mini_id
  164. )
  165. root_share_id, source_id, productionPath = self.create_gzh_path(
  166. video_id, user_id, gh_id
  167. )
  168. source = "Web"
  169. logging(
  170. code="1002",
  171. info="root_share_id --{}, productionPath -- {}".format(
  172. root_share_id, productionPath
  173. ),
  174. function="process",
  175. trace_id=self.trace_id,
  176. )
  177. result = {
  178. "productionCover": productionCover,
  179. "productionName": productionName,
  180. "programAvatar": programAvatar,
  181. "programId": programId,
  182. "programName": programName,
  183. "source": source,
  184. "rootShareId": root_share_id,
  185. "productionPath": productionPath,
  186. "videoUrl": videoUrl,
  187. "mini_id": mini_id,
  188. "paragraphPosition": index * 0.25,
  189. }
  190. # if gh_id in self.test_id_set and index == 1:
  191. # 只针对插入的第一个小程序位置做改变
  192. if index == 1:
  193. result['paragraphPosition'] = 0.01
  194. update_result_sql = f"""
  195. UPDATE {db_article}
  196. SET
  197. result{index} = %s,
  198. success = %s
  199. WHERE
  200. trace_id = %s;
  201. """
  202. await self.mysql_client.async_insert(
  203. sql=update_result_sql,
  204. params=(json.dumps(result, ensure_ascii=False), 1, self.trace_id),
  205. )
  206. logging(
  207. code="2000",
  208. info="统计 root_share_id && video_id",
  209. function="process",
  210. trace_id=self.trace_id,
  211. data={
  212. "rootShareId": root_share_id,
  213. "videoId": video_id,
  214. "sourceId": source_id,
  215. },
  216. )
  217. return result
  218. async def generate_cards(self, video_list, kimi_title, gh_id):
  219. """
  220. 生成一组卡片
  221. :param video_list:
  222. :param kimi_title:
  223. :param gh_id:
  224. :return:
  225. """
  226. L = []
  227. if self.mini_program_type == 1:
  228. # mini_id_list = [25, 29, 31]
  229. # video_count = len(video_list)
  230. # mini_choice_index = random.sample(range(3), video_count)
  231. # mini_choice_item = [mini_id_list[i] for i in mini_choice_index]
  232. for index, video_id in enumerate(video_list, 1):
  233. random_num = random.randint(1, 10)
  234. if random_num in [1, 2, 3, 4, 5, 6]:
  235. mini_id = 25
  236. elif random_num in [7, 8]:
  237. mini_id = 29
  238. else:
  239. mini_id = 31
  240. result = await self.generate_card(
  241. video_id=video_id,
  242. kimi_title=kimi_title,
  243. index=index,
  244. gh_id=gh_id,
  245. mini_id=mini_id,
  246. )
  247. L.append(result)
  248. elif self.mini_program_type == 2:
  249. for index, video_id in enumerate(video_list, 1):
  250. result = await self.generate_card(
  251. video_id=video_id,
  252. kimi_title=kimi_title,
  253. index=index,
  254. gh_id=gh_id,
  255. mini_id=33,
  256. )
  257. L.append(result)
  258. elif self.mini_program_type == 3:
  259. for index, video_id in enumerate(video_list, 1):
  260. result = await self.generate_card(
  261. video_id=video_id,
  262. kimi_title=kimi_title,
  263. index=index,
  264. gh_id=gh_id,
  265. mini_id=27,
  266. )
  267. L.append(result)
  268. return L
  269. async def deal(self):
  270. """
  271. Recall Deal
  272. :return:
  273. """
  274. response = await self.get_result()
  275. status_code = response.get("content_status")
  276. process_times = response.get("process_times")
  277. if status_code == 0:
  278. if process_times > 3:
  279. result = {
  280. "traceId": self.trace_id,
  281. "code": 0,
  282. "error": "匹配失败,处理超过五次,文章敏感",
  283. }
  284. else:
  285. result = {
  286. "traceId": self.trace_id,
  287. "code": 0,
  288. "Message": "该请求还没处理",
  289. }
  290. elif status_code == 1:
  291. result = {
  292. "traceId": self.trace_id,
  293. "code": 1,
  294. "Message": "该请求正在处理中",
  295. }
  296. elif status_code == 2:
  297. unEmptyList = [i for i in response["vid_list"] if i]
  298. cards = await self.generate_cards(
  299. unEmptyList, response.get("kimi_title"), response["gh_id"]
  300. )
  301. if cards:
  302. result = {"traceId": self.trace_id, "miniprogramList": cards}
  303. else:
  304. result = {
  305. "traceId": self.trace_id,
  306. "code": 0,
  307. "error": "匹配失败,视频下载失败返回vid为0",
  308. }
  309. elif status_code == 3:
  310. result = {
  311. "traceId": self.trace_id,
  312. "code": 0,
  313. "error": "匹配失败,处理超过五次,文章敏感",
  314. }
  315. else:
  316. result = {"traceId": self.trace_id, "Message": "UnKnow Error"}
  317. logging(
  318. code="1002",
  319. info="返回结果",
  320. function="process",
  321. data=result,
  322. trace_id=self.trace_id,
  323. )
  324. return result