response.py 12 KB

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