VbotLib.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php
  2. namespace addons\vbot\library;
  3. /**
  4. *
  5. */
  6. class VbotLib
  7. {
  8. // 模板数据
  9. public $template;
  10. // 要覆盖的模板数据 (参见:\application\admin\controller\dinghorn\Example.php 的 example2 方法)
  11. public $tpl_data;
  12. // 模板变量键值对,若模板变量已预先定义,则会自动获取值,无需在此传递
  13. public $tpl_variable;
  14. /**
  15. * 构造方法
  16. * @param array $template 模板数据
  17. * @param array $tpl_data 要覆盖的模板数据
  18. * @param array $tpl_variable 模板变量键值对
  19. */
  20. public function __construct($template = array(), $tpl_data = array(), $tpl_variable = array())
  21. {
  22. $this->template = $template;
  23. $this->tpl_data = $tpl_data;
  24. $this->tpl_variable = $tpl_variable;
  25. }
  26. /**
  27. * 发起请求
  28. *
  29. * @param string $access_token 机器人的 access_token
  30. * @param array post_data 请求数据
  31. * @return array 请求结果
  32. */
  33. /**
  34. * 发起请求
  35. * @param string $webhook 机器人的 WebHook地址
  36. * @param array $post_data 请求数据
  37. * @return array 请求结果
  38. */
  39. public function msgSend($webhook, $post_data)
  40. {
  41. $ch = curl_init();
  42. curl_setopt($ch, CURLOPT_URL, $webhook);
  43. curl_setopt($ch, CURLOPT_POST, 1);
  44. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
  45. curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json;charset=utf-8'));
  46. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
  47. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  48. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
  49. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
  50. $ret = curl_exec($ch);
  51. if (false == $ret) {
  52. // curl_exec failed
  53. $result = ['errcode' => -2, 'errmsg' => curl_error($ch)];
  54. } else {
  55. $rsp = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  56. if (200 != $rsp) {
  57. $result = ['errcode' => -1, 'errmsg' => $rsp . ' ' . curl_error($ch)];
  58. } else {
  59. $result = json_decode($ret, true);
  60. if (!$result) {
  61. $result = ['errcode' => -3, 'errmsg' => '转换请求结果数据失败!'];
  62. }
  63. }
  64. }
  65. curl_close($ch);
  66. return $result;
  67. }
  68. /**
  69. * 组装消息数据
  70. * @return array 组装结果
  71. */
  72. public function deal_with_msg()
  73. {
  74. $msg_data = array();
  75. $msgtype = $msg_data['msgtype'] = $this->template['typelist'];
  76. $content = isset($this->tpl_data['content']) ? $this->analysis_variable($this->tpl_data['content']) : $this->analysis_variable($this->template['content']);
  77. if ($msgtype == 'text') {
  78. $msg_data['text'] = [
  79. 'content' => $content,
  80. 'mentioned_mobile_list' => $this->deal_with_at($this->template)
  81. ];
  82. } elseif ($msgtype == 'markdown') {
  83. $msg_data['markdown'] = [
  84. 'content' => $content
  85. ];
  86. } elseif ($msgtype == 'image') {
  87. $picurl_image = isset($this->tpl_data['picurl_image']) ? $this->tpl_data['picurl_image'] : request()->domain() . $this->template['picurl_image'];
  88. $base64 = base64_encode(@file_get_contents($picurl_image));
  89. $msg_data['image'] = [
  90. 'base64' => $base64,
  91. 'md5' => md5(@file_get_contents($picurl_image))
  92. ];
  93. } elseif ($msgtype == 'news') {
  94. $news = isset($this->tpl_data['news']) ? $this->tpl_data['news'] : json_decode($this->template['news'], true);
  95. foreach ($news as $key => $value) {
  96. $news[$key]['title'] = $this->analysis_variable($news[$key]['title']);
  97. $news[$key]['description'] = '';
  98. }
  99. $news[0]['description'] = $content;
  100. $msg_data['news'] = array(
  101. 'articles' => $news
  102. );
  103. }
  104. return $msg_data;
  105. }
  106. /**
  107. * 分析字符串中的自定义变量
  108. * @param string $str 要分析的字符串
  109. * @return string 解析过变量的字符串
  110. */
  111. public function analysis_variable($str)
  112. {
  113. if (!$str) {
  114. return '';
  115. }
  116. $variables = array();
  117. $match = array();
  118. preg_match_all('/\${(.*?)}/', $str, $match);// 匹配到所有变量
  119. // 读取数据库中的模板变量
  120. $variable_tmp = \think\Db::name('vbot_variable')->where('deletetime', null)->select();
  121. foreach ($variable_tmp as $key => $value) {
  122. $value['variable_type'] = 'predefined';// 标记为预定义
  123. $variable_arr[$value['name']] = $value;
  124. }
  125. unset($variable_tmp);
  126. // 准备传递过来的模板变量
  127. foreach ($this->tpl_variable as $key => $value) {
  128. $variable_arr[$key] = [
  129. 'variable_type' => 'definition_now',// 标记为现在定义
  130. 'variable_value' => $value,
  131. ];
  132. }
  133. foreach ($match[1] as $key => $value) {
  134. if (array_key_exists($value, $variable_arr)) {
  135. if ($variable_arr[$value]['variable_type'] == 'definition_now') {
  136. $str = str_replace($match[0][$key], $variable_arr[$value]['variable_value'], $str);
  137. } else if ($variable_arr[$value]['variable_type'] == 'predefined') {
  138. $variable_value = $this->get_variable_value($variable_arr[$value]);
  139. $str = str_replace($match[0][$key], $variable_value, $str);
  140. }
  141. }
  142. }
  143. return $str;
  144. }
  145. /**
  146. * 获取数据库中的模板变量的值
  147. * @param string $var 变量数据
  148. * @return string 变量值
  149. */
  150. public function get_variable_value($var)
  151. {
  152. if ($var['value_source'] == 0) {
  153. $var['sql'] = str_replace('__PREFIX__', config('database.prefix'), $var['sql']);
  154. $res = \think\Db::query($var['sql']);
  155. if ($res) {
  156. if (is_array($res[0])) {
  157. foreach ($res[0] as $key => $value) {
  158. return $value;
  159. }
  160. } else {
  161. return $res[0];
  162. }
  163. } else {
  164. return false;
  165. }
  166. } elseif ($var['value_source'] == 1) {
  167. return \think\Hook::exec($var['namespace'] . '\\' . $var['class'], $var['function'], $var['params']);
  168. }
  169. }
  170. /**
  171. * 组装at数据
  172. * @return array 组装结果
  173. */
  174. public function deal_with_at()
  175. {
  176. if (isset($this->tpl_data['is_atall']) || isset($this->tpl_data['at_mobiles'])) {
  177. $this->template['is_atall'] = $this->tpl_data['is_atall'];
  178. $this->template['at_mobiles'] = $this->tpl_data['at_mobiles'];
  179. }
  180. if ($this->template['is_atall']) {
  181. return ['', "@all"];
  182. } else {
  183. $at_mobiles = explode(',', rtrim($this->template['at_mobiles'], ','));
  184. return $at_mobiles;
  185. }
  186. }
  187. }