MessageMediaDispatch.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. <?php
  2. /**
  3. * Created by: PhpStorm
  4. * User: lytian
  5. * Date: 2020/2/25
  6. * Time: 14:23
  7. */
  8. namespace app\admin\command;
  9. use app\main\service\HigeMessageService;
  10. use app\main\service\MiniProgramService;
  11. use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
  12. use EasyWeChat\Kernel\Messages\Article;
  13. use think\console\Command;
  14. use think\console\Input;
  15. use think\console\Output;
  16. use think\Db;
  17. use think\Exception;
  18. use think\Log;
  19. use think\Request;
  20. class MessageMediaDispatch extends BaseCommand
  21. {
  22. private $wxUrlArr = [];
  23. protected function configure()
  24. {
  25. $this->setName('messageMediaDispatch')
  26. ->setDescription('高级群发之处理媒体资源');
  27. }
  28. protected function execute(Input $input, Output $output)
  29. {
  30. Request::instance()->module('admin'); //cli模式下无法获取到当前的项目模块,手动指定一下
  31. $do = true;
  32. $messageArr = [];
  33. while ($do) {
  34. $version = substr(time(), 5) . mt_rand(1000, 9999);
  35. //设置锁
  36. Db::execute("UPDATE send_channel_message SET version = {$version} WHERE `media_status` = 0 AND `version` = 0 ORDER BY id ASC LIMIT 50");
  37. $channelMessages = model("SendChannelMessage")->where('version', 'eq', $version)->where('media_status', 'eq', 0)->select();
  38. if ($channelMessages) {
  39. foreach ($channelMessages as $channelMessage) {
  40. //主消息
  41. try {
  42. if (!isset($messageArr[$channelMessage['mass_id']])) {
  43. $message = model("SendMessage")->where('id', 'eq', $channelMessage['mass_id'])->find();
  44. $messageArr[$channelMessage['mass_id']] = $message;
  45. } else {
  46. $message = $messageArr[$channelMessage['mass_id']];
  47. }
  48. $contentArr = json_decode($message['message_content'], true);
  49. $content = $this->parseContent($channelMessage['channel_id'], $channelMessage['type'], $contentArr, $channelMessage);
  50. $update = [
  51. 'version' => 1,
  52. 'media_status' => 3,
  53. 'media_updatetime' => time(),
  54. 'updatetime' => time()
  55. ];
  56. switch ($channelMessage['type']) {
  57. case 1:
  58. if ($content) {
  59. $content = implode("\n\n", $content);
  60. $update['message_content'] = $content;
  61. } else {
  62. //内容为空 直接更新为失败
  63. $update['send_status'] = 3;
  64. $update['media_status'] = 2;
  65. }
  66. break;
  67. case 2:
  68. if ($content) {
  69. //创建图文素材
  70. $articles = [];
  71. foreach ($content as $item) {
  72. $articles[] = new Article($item);
  73. }
  74. $res = HigeMessageService::instance()->uploadNews($channelMessage['channel_id'], $articles);
  75. if (isset($res['errcode'])) {
  76. //判断是否是没评论权限导致失败
  77. if ($res['errcode'] == 88000) {
  78. $newArticles = [];
  79. foreach ($content as $item) {
  80. unset($item['need_open_comment']);
  81. unset($item['only_fans_can_comment']);
  82. $newArticles[] = new Article($item);
  83. }
  84. $ress = HigeMessageService::instance()->uploadNews($channelMessage['channel_id'], $newArticles);
  85. if (isset($ress['errcode'])) {
  86. //素材处理失败
  87. $update['media_status'] = 2;
  88. } else {
  89. $update['wx_media_id'] = $ress['media_id'];
  90. }
  91. } else {
  92. //素材处理失败
  93. $update['media_status'] = 2;
  94. }
  95. } else {
  96. $update['wx_media_id'] = $res['media_id'];
  97. }
  98. } else {
  99. //内容为空 直接更新为失败
  100. $update['send_status'] = 3;
  101. $update['media_status'] = 2;
  102. }
  103. break;
  104. case 3:
  105. $mediaResult = HigeMessageService::instance()->image2media($channelMessage['channel_id'], $content['img_path']);
  106. if (isset($mediaResult['errcode'])) {
  107. //素材处理失败
  108. $update['media_status'] = 2;
  109. } else {
  110. $update['wx_media_id'] = $mediaResult['media_id'];
  111. }
  112. break;
  113. }
  114. model("SendChannelMessage")->update($update, ['id' => $channelMessage['id']]);
  115. } catch (Exception $e) {
  116. Log::error("渠道消息资源处理失败:msg: {$e->getMessage()} line : {$e->getLine()}");
  117. }
  118. }
  119. } else {
  120. $do = false;
  121. }
  122. }
  123. //更新已完成主任务
  124. $maps = [
  125. 'send_status' => 2,
  126. 'message_status' => 1,
  127. ];
  128. $massMessages = model("SendMessage")->where($maps)->field("id, subscription_ids")->select();
  129. if ($massMessages) {
  130. foreach ($massMessages as $massMessage) {
  131. $channelIds = array_unique(array_filter(explode(',', $massMessage['subscription_ids'])));
  132. $messages = Db::query("SELECT count(media_status=0 or null) count_0, count(media_status=1 or null) count_1, count(media_status=2 or null) count_2, count(media_status=3 or null) count_3 FROM send_channel_message WHERE mass_id = {$massMessage['id']};");
  133. $result = $messages[0] ?? [];
  134. if ($result) {
  135. if ($result['count_0'] != 0 || $result['count_1'] != 0) {
  136. continue;
  137. } elseif ($result['count_2'] == count($channelIds)) {
  138. //全部失败
  139. model("SendMessage")->update(['send_status' => 6, 'updatetime' => time()], ['id' => $massMessage['id']]);
  140. } elseif ($result['count_3'] > 0) {
  141. //全部处理完成
  142. model("SendMessage")->update(['send_status' => 3, 'updatetime' => time()], ['id' => $massMessage['id']]);
  143. }
  144. }
  145. }
  146. }
  147. }
  148. /**
  149. * 格式化内容
  150. * @param $channelId
  151. * @param $msgType
  152. * @param $message
  153. * @param $channelMessage
  154. * @return array|mixed|string
  155. * @throws Exception
  156. * @throws InvalidArgumentException
  157. */
  158. private function parseContent($channelId, $msgType, $message, $channelMessage)
  159. {
  160. if ($msgType == 1) {
  161. //文字消息
  162. $content = '';
  163. $str_list = [];
  164. foreach ($message as $idx => $item) {
  165. if (isset($item['url'])) {
  166. $str = '';
  167. $str .= "<a href=\"" . $item['url'] . "\">";
  168. $str .= $item['content'];
  169. $str .= "</a>";
  170. $str_list[] = $str;
  171. } else {
  172. if (isset($item['page']) && $item['page']){
  173. $item['content'] = MiniProgramService::instance()->getMiniText($item['page'],$item['content'],$channelId);
  174. }
  175. $str_list[] = $item['content'];
  176. }
  177. }
  178. return $str_list;
  179. } elseif ($msgType == 2) {
  180. //图文消息
  181. $newsData = [];
  182. $messageCount = count($message);
  183. foreach ($message as $k => $item) {
  184. //处理小程序
  185. HigeMessageService::instance()->__setMiniBatch($item,$channelId);
  186. $article = [
  187. 'title' => $item['title'],
  188. 'author' => $item['author'],
  189. 'thumb_media_id' => '',
  190. 'digest' => '',
  191. 'auth' => '',
  192. 'show_cover' => 0,
  193. 'content' => $this->parseContentImage($channelId, $item['content']),
  194. 'source_url' => '',
  195. 'need_open_comment' => $item['need_open_comment'] ?? 0,
  196. 'only_fans_can_comment' => $item['only_fans_can_comment'] ?? 0,
  197. ];
  198. $url = '';
  199. if (isset($item['type']) && $item['type'] != 4 ) {
  200. $url = HigeMessageService::instance()->buildUrl($channelId, $item);
  201. //进行打点操作
  202. if (in_array($item['type'], [1, 3]) && empty($url)) {
  203. Log::error("error 活动状态异常 message_id: {$channelMessage['id']}");
  204. continue;
  205. }
  206. $url = HigeMessageService::instance()->buildPointInfo($channelId, $msgType, $url, $channelMessage['send_time'], $channelMessage['id'], $k);
  207. }
  208. $article['source_url'] = $url;
  209. if ($item['cover']) {
  210. $coverResult = HigeMessageService::instance()->image2media($channelId, $item['cover'], 1);
  211. if (isset($coverResult['errcode'])) {
  212. Log::error("error:封面图上传失败 message_id: {$channelMessage['id']}");
  213. continue;
  214. } else {
  215. $article['thumb_media_id'] = $coverResult['media_id'];
  216. }
  217. } else {
  218. Log::error("error:缺少封面图 message_id: {$channelMessage['id']}");
  219. continue;
  220. }
  221. //if ($messageCount > 1) {
  222. $article['digest'] = (isset($item['digest']) && !empty($item['digest'])) ? $item['digest'] : mb_substr(strip_tags($item['content']), 0, 64);
  223. //}
  224. $newsData[] = $article;
  225. }
  226. return $newsData;
  227. } elseif ($msgType == 3) {
  228. //图片消息
  229. $imgPath = current($message);
  230. return $imgPath;
  231. }
  232. }
  233. /**
  234. * 处理内容中的图片
  235. * @param $channelId
  236. * @param $content
  237. * @return mixed
  238. * @throws Exception
  239. * @throws InvalidArgumentException
  240. */
  241. private function parseContentImage($channelId, $content)
  242. {
  243. $imgPaths = [];
  244. if (preg_match_all("/src=['|\"]([^\s]*)['|\"]/i", $content, $m)) {
  245. $imgPaths = $m[1];
  246. }
  247. if ($imgPaths) {
  248. $mediaArr = [];
  249. foreach ($imgPaths as $k => $imgPath) {
  250. if (isset($this->wxUrlArr[$imgPath])) {
  251. $wxUrl = $this->wxUrlArr[$imgPath];
  252. } else {
  253. $res = HigeMessageService::instance()->image2media($channelId, $imgPath);
  254. if (isset($res['errcode'])) {
  255. Log::error("error 图片上传失败");
  256. $wxUrl = $imgPaths;
  257. } else {
  258. $wxUrl = $res['url'];
  259. $this->wxUrlArr[$imgPath] = $res['url'];
  260. }
  261. }
  262. $mediaArr[$k] = $wxUrl;
  263. }
  264. $content = str_replace($imgPaths, $mediaArr, $content);
  265. }
  266. return $content;
  267. }
  268. }