MqDiscussion.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. <?php
  2. namespace App\Console\Commands;
  3. use Illuminate\Console\Command;
  4. use Illuminate\Support\Facades\Log;
  5. use Illuminate\Support\Str;
  6. use App\Models\Sentence;
  7. use App\Models\WebHook;
  8. use App\Models\Discussion;
  9. use App\Models\Article;
  10. use App\Models\DhammaTerm;
  11. use App\Models\Wbw;
  12. use App\Models\WbwBlock;
  13. use App\Http\Api\Mq;
  14. use App\Tools\WebHook as WebHookSend;
  15. use App\Http\Api\MdRender;
  16. use App\Http\Api\UserApi;
  17. use App\Http\Controllers\NotificationController;
  18. class MqDiscussion extends Command
  19. {
  20. /**
  21. * The name and signature of the console command.
  22. * php artisan mq:discussion
  23. * @var string
  24. */
  25. protected $signature = 'mq:discussion';
  26. /**
  27. * The console command description.
  28. *
  29. * @var string
  30. */
  31. protected $description = 'Command description';
  32. /**
  33. * Create a new command instance.
  34. *
  35. * @return void
  36. */
  37. public function __construct()
  38. {
  39. parent::__construct();
  40. }
  41. /**
  42. * Execute the console command.
  43. *
  44. * @return int
  45. */
  46. public function handle()
  47. {
  48. if(\App\Tools\Tools::isStop()){
  49. return 0;
  50. }
  51. $exchange = 'router';
  52. $queue = 'discussion';
  53. $this->info(" [*] Waiting for {$queue}. To exit press CTRL+C");
  54. Log::info("discussion worker start .");
  55. Mq::worker($exchange,$queue,function ($message){
  56. Log::info('mq discussion receive {message}',['message'=>json_encode($message,JSON_UNESCAPED_UNICODE)]);
  57. $result = 0;
  58. $msgParam = array();
  59. $msgParam['nickname'] = $message->editor->nickName;
  60. $link = config('app.url')."/pcd/discussion/topic/";
  61. if($message->parent){
  62. $msgParam['topic-title'] = Discussion::where('id',$message->parent)->value('title');
  63. $id = $message->id;
  64. $msgParam['link'] = $link . $message->parent.'#'.$id;
  65. $msgParam['card_title'] = "回复讨论";
  66. $type = 'reply';
  67. }else{
  68. $msgParam['title'] = $message->title;
  69. $msgParam['link'] = $link . $message->id;
  70. $msgParam['card_title'] = "创建讨论";
  71. $type = 'create';
  72. }
  73. if($message->content){
  74. $msgParam['content'] = $message->content;
  75. }
  76. switch ($message->res_type) {
  77. case 'sentence':
  78. $sentence = Sentence::where('uid',$message->res_id)->first();
  79. if(!$sentence){
  80. Log::error('invalid sentence id '.$message->res_id);
  81. $result = 1;
  82. break;
  83. }
  84. //站内信
  85. try{
  86. $sendTo = array();
  87. //句子的channel拥有者
  88. //$sendTo[] = $prData->channel->studio_id;
  89. //句子的作者
  90. if(!in_array($sentence->editor_uid,$sendTo)){
  91. $sendTo[] = $sentence->editor_uid;
  92. }
  93. //句子的采纳者
  94. if(!empty($sentence->acceptor_uid) && !in_array($sentence->acceptor_uid,$sendTo)){
  95. $sendTo[] = $sentence->acceptor_uid;
  96. }
  97. $this->notification($message->editor->uid,
  98. $sendTo,
  99. 'discussion',
  100. $message->id,
  101. $sentence->channel_uid);
  102. }catch(\Exception $e){
  103. Log::error('send notification failed',['exception'=>$e]);
  104. }
  105. //webhook
  106. $contentHtml = MdRender::render($sentence->content,
  107. [$sentence->channel_uid],
  108. null,
  109. 'read',
  110. 'translation',
  111. $sentence->content_type);
  112. $contentTxt = strip_tags($contentHtml);
  113. /**生成消息内容 */
  114. $msgParam['anchor-content'] = $contentTxt;
  115. $WebHookResId = $sentence->channel_uid;
  116. $this->WebHook($msgParam,$type,$WebHookResId);
  117. break;
  118. case 'wbw':
  119. $wbw = Wbw::where('uid',$message->res_id)->first();
  120. if(!$wbw){
  121. Log::error('invalid wbw id '.$message->res_id);
  122. $result = 1;
  123. break;
  124. }
  125. $wbwBlock = WbwBlock::where('uid',$wbw->block_uid)->first();
  126. if(!$wbwBlock){
  127. Log::error('invalid wbw-block id '.$message->res_id);
  128. $result = 1;
  129. break;
  130. }
  131. //站内信
  132. try{
  133. $sendTo = array();
  134. //channel拥有者
  135. //$sendTo[] = $prData->channel->studio_id;
  136. //作者
  137. if(!in_array($wbw->creator_uid,$sendTo)){
  138. $sendTo[] = $wbw->creator_uid;
  139. }
  140. //提问者
  141. if(!empty($message->parent)){
  142. $topicEditor = Discussion::where('id',$message->parent)
  143. ->value('editor_uid');
  144. if(!empty($topicEditor) && !in_array($topicEditor,$sendTo)){
  145. $sendTo[] = $topicEditor;
  146. Log::debug('发送给提问者',['data'=>$topicEditor]);
  147. }
  148. }
  149. $this->notification($message->editor->id,
  150. $sendTo,
  151. 'discussion',
  152. $message->id,
  153. $wbwBlock->channel_uid);
  154. }catch(\Exception $e){
  155. Log::error('send notification failed',['exception'=>$e]);
  156. }
  157. $msgParam['anchor-content'] = $wbw->word;
  158. $WebHookResId = $wbwBlock->channel_uid;
  159. $this->WebHook($msgParam,$type,$WebHookResId);
  160. break;
  161. case 'term':
  162. $term = DhammaTerm::where('guid',$message->res_id)->first();
  163. if(!$term){
  164. Log::error('invalid term id '.$message->res_id);
  165. $result = 1;
  166. break;
  167. }
  168. if(empty($term->channal) || !Str::isUuid($term->channal)){
  169. break;
  170. }
  171. //站内信
  172. try{
  173. $sendTo = array();
  174. //拥有者
  175. $sendTo[] = $term->term;
  176. //作者
  177. $editor = App\Http\Api\UserApi::getById($term->editor_id);
  178. if($editor['id'] !== 0 && !in_array($editor['uid'],$sendTo)){
  179. $sendTo[] = $editor['uid'];
  180. }
  181. $this->notification($message->editor->uid,
  182. $sendTo,
  183. 'discussion',
  184. $message->id,
  185. $term->channal);
  186. }catch(\Exception $e){
  187. Log::error('send notification failed',['exception'=>$e]);
  188. }
  189. //webhook
  190. $msgParam['anchor-content'] = $term->meaning . '(' . $term->word . ')';
  191. $WebHookResId = $term->channal;
  192. $this->WebHook($msgParam,$WebHookResId);
  193. break;
  194. default:
  195. # code...
  196. break;
  197. }
  198. return $result;
  199. });
  200. return 0;
  201. }
  202. private function WebHook($msgParam,$type,$resId){
  203. $rootId = UserApi::getById(0)['uid'];
  204. $articleTitle = "webhook://discussion/{$type}/zh-hans";
  205. $tpl = Article::where('owner',$rootId)
  206. ->where('title',$articleTitle)
  207. ->value('content');
  208. if(empty($tpl)){
  209. Log::error('mq:discussion 模版不能为空',['tpl_title'=>$articleTitle]);
  210. return 1;
  211. }
  212. $m = new \Mustache_Engine(array('entity_flags'=>ENT_QUOTES,
  213. 'delimiters' => '{% %}',));
  214. $msgContent = $m->render($tpl,$msgParam);
  215. $webhooks = WebHook::where('res_id',$resId)
  216. ->where('status','active')
  217. ->get();
  218. foreach ($webhooks as $key => $hook) {
  219. $event = json_decode($hook->event);
  220. if(is_array($event)){
  221. if(!in_array('discussion',$event)){
  222. continue;
  223. }
  224. }else{
  225. continue;
  226. }
  227. $command = '';
  228. $whSend = new WebHookSend;
  229. $ok = 0;
  230. switch ($hook->receiver) {
  231. case 'dingtalk':
  232. $ok = $whSend->dingtalk($hook->url,$msgParam['card_title'],$msgContent);
  233. break;
  234. case 'wechat':
  235. $ok = $whSend->wechat($hook->url,null,$msgContent);
  236. break;
  237. default:
  238. $ok=2;
  239. break;
  240. }
  241. $result += $ok;
  242. $logMsg = "{$command} ok={$ok}";
  243. if($ok === 0){
  244. $this->info($logMsg);
  245. }else{
  246. $this->error($logMsg);
  247. }
  248. if($ok === 0){
  249. Log::debug('mq:discussion: send success {url}',['url'=>$hook->url]);
  250. WebHook::where('id',$hook->id)->increment('success');
  251. }else{
  252. Log::error('mq:discussion: send fail {url}',['url'=>$hook->url]);
  253. WebHook::where('id',$hook->id)->increment('fail');
  254. }
  255. }
  256. }
  257. private function notification($from,$to,$resType,$resId,$channel){
  258. //发送站内信
  259. try{
  260. $sendCount = NotificationController::insert(
  261. $from,
  262. $to,
  263. $resType,
  264. $resId,
  265. $channel);
  266. $this->info("send notification success to [".$sendCount.'] users');
  267. }catch(\Exception $e){
  268. Log::error('send notification failed',['exception'=>$e]);
  269. }
  270. return;
  271. }
  272. }