api.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. <?php
  2. //更多资源请关注三岁半资源网:https://sansuib.com
  3. /**
  4. * [WeEngine System] Copyright (c) 2014 WE7.CC
  5. * WeEngine is NOT a free software, it under the license terms, visited http://www.we7.cc/ for more details.
  6. */
  7. define('IN_API', true);
  8. require_once './framework/bootstrap.inc.php';
  9. load()->model('reply');
  10. load()->model('attachment');
  11. load()->model('visit');
  12. load()->app('common');
  13. load()->classs('wesession');
  14. $hash = $_GPC['hash'];
  15. if(!empty($hash)) {
  16. $id = pdo_fetchcolumn("SELECT acid FROM " . tablename('account') . " WHERE hash = :hash", array(':hash' => $hash));
  17. }
  18. if(!empty($_GPC['appid'])) {
  19. $appid = ltrim($_GPC['appid'], '/');
  20. if ($appid == 'wx570bc396a51b8ff8') {
  21. $_W['account'] = array(
  22. 'type' => '3',
  23. 'key' => 'wx570bc396a51b8ff8',
  24. 'level' => 4,
  25. 'token' => 'platformtestaccount'
  26. );
  27. } else {
  28. $id = pdo_fetchcolumn("SELECT acid FROM " . tablename('account_wechats') . " WHERE `key` = :appid", array(':appid' => $appid));
  29. }
  30. }
  31. if(empty($id)) {
  32. $id = intval($_GPC['id']);
  33. }
  34. if (!empty($id)) {
  35. $uniacid = pdo_getcolumn('account', array('acid' => $id), 'uniacid');
  36. $_W['account'] = $_W['uniaccount'] = uni_fetch($uniacid);
  37. if (!empty($_W['account']['uniacid']) && visit_app_pass_visit_limit($_W['account']['uniacid'])) {
  38. exit('success');
  39. }
  40. }
  41. if(empty($_W['account'])) {
  42. exit('initial error hash or id');
  43. }
  44. if(empty($_W['account']['token'])) {
  45. exit('initial missing token');
  46. }
  47. $_W['debug'] = intval($_GPC['debug']);
  48. $_W['acid'] = $_W['account']['acid'];
  49. $_W['uniacid'] = $_W['account']['uniacid'];
  50. $_W['account']['groupid'] = $_W['uniaccount']['groupid'];
  51. $_W['account']['qrcode'] = $_W['attachurl'].'qrcode_'.$_W['acid'].'.jpg?time='.$_W['timestamp'];
  52. $_W['account']['avatar'] = $_W['attachurl'].'headimg_'.$_W['acid'].'.jpg?time='.$_W['timestamp'];
  53. $_W['attachurl'] = attachment_set_attach_url();
  54. register_shutdown_function('visit_update_today', 'app', 'we7_api');
  55. $engine = new WeEngine();
  56. if (!empty($_W['setting']['copyright']['status'])) {
  57. $engine->died('抱歉,站点已关闭,关闭原因:' . $_W['setting']['copyright']['reason']);
  58. }
  59. if (!empty($_W['uniaccount']['endtime']) && TIMESTAMP > $_W['uniaccount']['endtime'] && !in_array($_W['uniaccount']['endtime'], array(USER_ENDTIME_GROUP_EMPTY_TYPE, USER_ENDTIME_GROUP_UNLIMIT_TYPE))) {
  60. $engine->died('抱歉,您的公众号已过期,请及时联系管理员');
  61. }
  62. if($_W['isajax'] && $_W['ispost'] && $_GPC['flag'] == 1) {
  63. $engine->encrypt();
  64. }
  65. if($_W['isajax'] && $_W['ispost'] && $_GPC['flag'] == 2) {
  66. $engine->decrypt();
  67. }
  68. $_W['isajax'] = false;
  69. $engine->start();
  70. class WeEngine {
  71. private $account = null;
  72. private $modules = array();
  73. public $keyword = array();
  74. public $message = array();
  75. public function __construct() {
  76. global $_W;
  77. $this->account = WeAccount::create($_W['account']);
  78. if(strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
  79. $_W['modules'] = uni_modules();
  80. $this->modules = array_keys($_W['modules']);
  81. $this->modules[] = 'cover';
  82. $this->modules[] = 'default';
  83. $this->modules[] = 'reply';
  84. $this->modules = array_unique ($this->modules);
  85. }
  86. }
  87. public function encrypt() {
  88. global $_W;
  89. if(empty($this->account)) {
  90. exit('Miss Account.');
  91. }
  92. $timestamp = TIMESTAMP;
  93. $nonce = random(5);
  94. $token = $_W['account']['token'];
  95. $signkey = array($token, TIMESTAMP, $nonce);
  96. sort($signkey, SORT_STRING);
  97. $signString = implode($signkey);
  98. $signString = sha1($signString);
  99. $_GET['timestamp'] = $timestamp;
  100. $_GET['nonce'] = $nonce;
  101. $_GET['signature'] = $signString;
  102. $postStr = file_get_contents('php://input');
  103. if(!empty($_W['account']['encodingaeskey']) && strlen($_W['account']['encodingaeskey']) == 43 && !empty($_W['account']['key']) && $_W['setting']['development'] != 1) {
  104. $data = $this->account->encryptMsg($postStr);
  105. $array = array('encrypt_type' => 'aes', 'timestamp' => $timestamp, 'nonce' => $nonce, 'signature' => $signString, 'msg_signature' => $data[0], 'msg' => $data[1]);
  106. } else {
  107. $data = array('', '');
  108. $array = array('encrypt_type' => '', 'timestamp' => $timestamp, 'nonce' => $nonce, 'signature' => $signString, 'msg_signature' => $data[0], 'msg' => $data[1]);
  109. }
  110. exit(json_encode($array));
  111. }
  112. public function decrypt() {
  113. global $_W;
  114. if(empty($this->account)) {
  115. exit('Miss Account.');
  116. }
  117. $postStr = file_get_contents('php://input');
  118. if(!empty($_W['account']['encodingaeskey']) && strlen($_W['account']['encodingaeskey']) == 43 && !empty($_W['account']['key']) && $_W['setting']['development'] != 1) {
  119. $resp = $this->account->local_decryptMsg($postStr);
  120. } else {
  121. $resp = $postStr;
  122. }
  123. exit($resp);
  124. }
  125. public function start() {
  126. global $_W;
  127. if(empty($this->account)) {
  128. exit('Miss Account.');
  129. }
  130. if(!$this->account->checkSign()) {
  131. exit('Check Sign Fail.');
  132. }
  133. if(strtolower($_SERVER['REQUEST_METHOD']) == 'get') {
  134. $row = array();
  135. $row['isconnect'] = 1;
  136. pdo_update('account', $row, array('uniacid' => $_W['uniacid']));
  137. cache_delete(cache_system_key('uniaccount', array('uniacid' => $_W['uniacid'])));
  138. exit(htmlspecialchars($_GET['echostr']));
  139. }
  140. if(strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
  141. $postStr = file_get_contents('php://input');
  142. if(!empty($_GET['encrypt_type']) && $_GET['encrypt_type'] == 'aes') {
  143. $postStr = $this->account->decryptMsg($postStr);
  144. }
  145. WeUtility::logging('trace', $postStr);
  146. $message = $this->account->parse($postStr);
  147. $this->message = $message;
  148. if(empty($message)) {
  149. WeUtility::logging('waring', 'Request Failed');
  150. exit('Request Failed');
  151. }
  152. $_W['openid'] = $message['from'];
  153. $_W['fans'] = array('from_user' => $_W['openid']);
  154. $this->booking($message);
  155. if($message['event'] == 'unsubscribe') {
  156. $this->receive(array(), array(), array());
  157. exit();
  158. }
  159. $sessionid = md5($message['from'] . $message['to'] . $_W['uniacid']);
  160. session_id($sessionid);
  161. WeSession::start($_W['uniacid'], $_W['openid']);
  162. $_SESSION['openid'] = $_W['openid'];
  163. $pars = $this->analyze($message);
  164. $pars[] = array(
  165. 'message' => $message,
  166. 'module' => 'default',
  167. 'rule' => '-1',
  168. );
  169. $hitParam['rule'] = -2;
  170. $hitParam['module'] = '';
  171. $hitParam['message'] = $message;
  172. $hitKeyword = array();
  173. $response = array();
  174. foreach($pars as $par) {
  175. if(empty($par['module'])) {
  176. continue;
  177. }
  178. $par['message'] = $message;
  179. $response = $this->process($par);
  180. if($this->isValidResponse($response)) {
  181. $hitParam = $par;
  182. if(!empty($par['keyword'])) {
  183. $hitKeyword = $par['keyword'];
  184. }
  185. break;
  186. }
  187. }
  188. $response_debug = $response;
  189. $pars_debug = $pars;
  190. if($hitParam['module'] == 'default' && is_array($response) && is_array($response['params'])) {
  191. foreach($response['params'] as $par) {
  192. if(empty($par['module'])) {
  193. continue;
  194. }
  195. $response = $this->process($par);
  196. if($this->isValidResponse($response)) {
  197. $hitParam = $par;
  198. if(!empty($par['keyword'])) {
  199. $hitKeyword = $par['keyword'];
  200. }
  201. break;
  202. }
  203. }
  204. }
  205. WeUtility::logging('params', var_export($hitParam, true));
  206. WeUtility::logging('response', $response);
  207. $resp = $this->account->response($response);
  208. if(!empty($_GET['encrypt_type']) && $_GET['encrypt_type'] == 'aes') {
  209. $resp = $this->account->encryptMsg($resp);
  210. $resp = $this->account->xmlDetract($resp);
  211. }
  212. if($_W['debug']) {
  213. $_W['debug_data'] = array(
  214. 'resp' => $resp,
  215. 'is_default' => 0
  216. );
  217. if(count($pars_debug) == 1) {
  218. $_W['debug_data']['is_default'] = 1;
  219. $_W['debug_data']['params'] = $response_debug['params'];
  220. } else {
  221. array_pop($pars_debug);
  222. $_W['debug_data']['params'] = $pars_debug;
  223. }
  224. $_W['debug_data']['hitparam'] = $hitParam;
  225. $_W['modules']['cover'] = array('title' => '入口封面', 'name' => 'cover');
  226. load()->web('template');
  227. $process = template('utility/emulator', TEMPLATE_FETCH);
  228. echo json_encode(array('resp' => $resp, 'process' => $process));
  229. exit();
  230. }
  231. if ($resp !== 'success') {
  232. $mapping = array(
  233. '[from]' => $this->message['from'],
  234. '[to]' => $this->message['to'],
  235. '[rule]' => $this->params['rule']
  236. );
  237. $resp = str_replace(array_keys($mapping), array_values($mapping), $resp);
  238. }
  239. $reply_times_info = (array)$_SESSION['__reply_times'];
  240. if ($reply_times_info['content'] == $message['content']) {
  241. $new_times = intval($reply_times_info['times']) + 1;
  242. } else {
  243. $new_times = 1;
  244. }
  245. $_SESSION['__reply_times'] = array('content' => $message['content'], 'date' => date('Y-m-d'), 'times' => $new_times);
  246. ob_start();
  247. echo $resp;
  248. ob_start();
  249. $this->receive($hitParam, $hitKeyword, $response);
  250. ob_end_clean();
  251. exit();
  252. }
  253. WeUtility::logging('waring', 'Request Failed');
  254. exit('Request Failed');
  255. }
  256. private function isValidResponse($response) {
  257. if ($response === 'success') {
  258. return true;
  259. }
  260. if(is_array($response)) {
  261. if($response['type'] == 'text' && !empty($response['content'])) {
  262. return true;
  263. }
  264. if($response['type'] == 'news' && !empty($response['items'])) {
  265. return true;
  266. }
  267. if(!in_array($response['type'], array('text', 'news', 'image'))) {
  268. return true;
  269. }
  270. }
  271. return false;
  272. }
  273. private function booking($message) {
  274. global $_W;
  275. if ($message['event'] == 'unsubscribe' || $message['event'] == 'subscribe') {
  276. $todaystat = pdo_get('stat_fans', array('date' => date('Ymd'), 'uniacid' => $_W['uniacid']));
  277. if ($message['event'] == 'unsubscribe') {
  278. if (empty($todaystat)) {
  279. $updatestat = array(
  280. 'new' => 0,
  281. 'uniacid' => $_W['uniacid'],
  282. 'cancel' => 1,
  283. 'cumulate' => 0,
  284. 'date' => date('Ymd'),
  285. );
  286. pdo_insert('stat_fans', $updatestat);
  287. } else {
  288. $updatestat = array(
  289. 'cancel' => $todaystat['cancel'] + 1,
  290. );
  291. pdo_update('stat_fans', $updatestat, array('id' => $todaystat['id']));
  292. }
  293. } elseif ($message['event'] == 'subscribe') {
  294. if (empty($todaystat)) {
  295. $updatestat = array(
  296. 'new' => 1,
  297. 'uniacid' => $_W['uniacid'],
  298. 'cancel' => 0,
  299. 'cumulate' => 0,
  300. 'date' => date('Ymd'),
  301. );
  302. pdo_insert('stat_fans', $updatestat);
  303. } else {
  304. $updatestat = array(
  305. 'new' => $todaystat['new'] + 1,
  306. );
  307. pdo_update('stat_fans', $updatestat, array('id' => $todaystat['id']));
  308. }
  309. }
  310. }
  311. load()->model('mc');
  312. $setting = uni_setting($_W['uniacid'], array('passport'));
  313. $fans = mc_fansinfo($message['from']);
  314. $default_groupid = cache_load(cache_system_key('defaultgroupid', array('uniacid' => $_W['uniacid'])));
  315. if (empty($default_groupid)) {
  316. $default_groupid = pdo_fetchcolumn('SELECT groupid FROM ' .tablename('mc_groups') . ' WHERE uniacid = :uniacid AND isdefault = 1', array(':uniacid' => $_W['uniacid']));
  317. cache_write(cache_system_key('defaultgroupid', array('uniacid' => $_W['uniacid'])), $default_groupid);
  318. }
  319. if(!empty($fans)) {
  320. if ($message['event'] == 'unsubscribe') {
  321. cache_build_memberinfo($fans['uid']);
  322. pdo_update('mc_mapping_fans', array('follow' => 0, 'unfollowtime' => TIMESTAMP), array('fanid' => $fans['fanid']));
  323. pdo_delete('mc_fans_tag_mapping', array('fanid' => $fans['fanid']));
  324. } elseif ($message['event'] != 'ShakearoundUserShake' && $message['type'] != 'trace') {
  325. $rec = array();
  326. if (empty($fans['follow'])) {
  327. $rec['follow'] = 1;
  328. $rec['followtime'] = $message['time'];
  329. }
  330. $member = array();
  331. if(!empty($fans['uid'])){
  332. $member = mc_fetch($fans['uid']);
  333. }
  334. if (empty($member)) {
  335. if (!isset($setting['passport']) || empty($setting['passport']['focusreg'])) {
  336. $data = array(
  337. 'uniacid' => $_W['uniacid'],
  338. 'email' => md5($message['from']).'@we7.cc',
  339. 'salt' => random(8),
  340. 'groupid' => $default_groupid,
  341. 'createtime' => TIMESTAMP,
  342. );
  343. $data['password'] = md5($message['from'] . $data['salt'] . $_W['config']['setting']['authkey']);
  344. pdo_insert('mc_members', $data);
  345. $rec['uid'] = pdo_insertid();
  346. }
  347. }
  348. if(!empty($rec)){
  349. pdo_update('mc_mapping_fans', $rec, array('openid' => $message['from']));
  350. }
  351. }
  352. } else {
  353. if ($message['event'] == 'subscribe' || $message['type'] == 'text' || $message['type'] == 'image') {
  354. load()->model('mc');
  355. $force_init_member = false;
  356. if (!isset($setting['passport']) || empty($setting['passport']['focusreg'])) {
  357. $force_init_member = true;
  358. }
  359. mc_init_fans_info($message['from'], $force_init_member);
  360. }
  361. }
  362. }
  363. private function receive($par, $keyword, $response) {
  364. global $_W;
  365. fastcgi_finish_request();
  366. $subscribe = cache_load(cache_system_key('module_receive_enable'));
  367. if (empty($subscribe)) {
  368. $subscribe = cache_build_module_subscribe_type();
  369. }
  370. $modules = uni_modules();
  371. $obj = WeUtility::createModuleReceiver('core');
  372. $obj->message = $this->message;
  373. $obj->params = $par;
  374. $obj->response = $response;
  375. $obj->keyword = $keyword;
  376. $obj->module = 'core';
  377. $obj->uniacid = $_W['uniacid'];
  378. $obj->acid = $_W['acid'];
  379. if(method_exists($obj, 'receive')) {
  380. @$obj->receive();
  381. }
  382. load()->func('communication');
  383. if (empty($subscribe[$this->message['type']]) && !empty($this->message['event'])) {
  384. $subscribe[$this->message['type']] = $subscribe[strtolower($this->message['event'])];
  385. }
  386. if (!empty($subscribe[$this->message['type']])) {
  387. foreach ($subscribe[$this->message['type']] as $modulename) {
  388. if (!in_array($modulename, array_keys($modules))) {
  389. continue;
  390. }
  391. $params = array(
  392. 'i' => $GLOBALS['uniacid'],
  393. 'modulename' => $modulename,
  394. 'request' => json_encode($par),
  395. 'response' => json_encode($response),
  396. 'message' => json_encode($this->message),
  397. );
  398. $response = ihttp_request(wurl('utility/subscribe/receive'), $params, array(), 10);
  399. if (is_error($response) || $response['code'] != 200) {
  400. $response = ihttp_request($_W['siteroot'] . 'web/' . wurl('utility/subscribe/receive'), $params, array(), 10);
  401. }
  402. }
  403. }
  404. }
  405. private function analyze(&$message) {
  406. global $_W;
  407. $params = array();
  408. if(in_array($message['type'], array('event', 'qr'))) {
  409. $params = call_user_func_array(array($this, 'analyze' . $message['type']), array(&$message));
  410. if(!empty($params)) {
  411. return (array)$params;
  412. }
  413. }
  414. if(!empty($_SESSION['__contextmodule']) && in_array($_SESSION['__contextmodule'], $this->modules)) {
  415. if($_SESSION['__contextexpire'] > TIMESTAMP) {
  416. $params[] = array(
  417. 'message' => $message,
  418. 'module' => $_SESSION['__contextmodule'],
  419. 'rule' => $_SESSION['__contextrule'],
  420. 'priority' => $_SESSION['__contextpriority'],
  421. 'context' => true
  422. );
  423. return $params;
  424. } else {
  425. unset($_SESSION);
  426. session_destroy();
  427. }
  428. }
  429. $reply_times_info = (array)$_SESSION['__reply_times'];
  430. if (!empty($_W['account']['setting']) && !empty($reply_times_info) && intval($_W['account']['setting']['reply_setting']) > 0 && strtotime($reply_times_info['date']) >= strtotime(date('Y-m-d')) && $reply_times_info['times'] >= $_W['account']['setting']['reply_setting'] && $reply_times_info['content'] == $message['content']) {
  431. exit('success');
  432. }
  433. if(method_exists($this, 'analyze' . $message['type'])) {
  434. $temp = call_user_func_array(array($this, 'analyze' . $message['type']), array(&$message));
  435. if(!empty($temp) && is_array($temp)){
  436. $params += $temp;
  437. }
  438. } else {
  439. $params += $this->handler($message['type']);
  440. }
  441. return $params;
  442. }
  443. private function analyzeSubscribe(&$message) {
  444. global $_W;
  445. $params = array();
  446. $message['type'] = 'text';
  447. $message['redirection'] = true;
  448. if(!empty($message['scene'])) {
  449. $message['source'] = 'qr';
  450. $sceneid = trim($message['scene']);
  451. if (is_numeric($sceneid)) {
  452. $scene_condition = " `qrcid` = :sceneid";
  453. }else{
  454. $scene_condition = " `scene_str` = :sceneid";
  455. }
  456. $condition = array(':sceneid' => $sceneid, ':uniacid' => $_W['uniacid']);
  457. $qr = pdo_fetch("SELECT `id`, `keyword` FROM " . tablename('qrcode') . " WHERE {$scene_condition} AND `uniacid` = :uniacid", $condition);
  458. if(!empty($qr)) {
  459. $message['content'] = $qr['keyword'];
  460. if (!empty($qr['type']) && $qr['type'] == 'scene') {
  461. $message['msgtype'] = 'text';
  462. }
  463. $params += $this->analyzeText($message);
  464. return $params;
  465. }
  466. }
  467. $message['source'] = 'subscribe';
  468. $setting = uni_setting($_W['uniacid'], array('welcome'));
  469. if(!empty($setting['welcome'])) {
  470. $message['content'] = $setting['welcome'];
  471. $params += $this->analyzeText($message);
  472. }
  473. return $params;
  474. }
  475. private function analyzeQR(&$message) {
  476. global $_W;
  477. $params = array();
  478. $default_message = $message;
  479. $message['type'] = 'text';
  480. $message['redirection'] = true;
  481. if(!empty($message['scene'])) {
  482. $message['source'] = 'qr';
  483. $sceneid = trim($message['scene']);
  484. if (is_numeric($sceneid)) {
  485. $scene_condition = " `qrcid` = :sceneid";
  486. }else{
  487. $scene_condition = " `scene_str` = :sceneid";
  488. }
  489. $condition_params = array(':sceneid' => $sceneid, ':uniacid' => $_W['uniacid']);
  490. $qr = pdo_fetch("SELECT `id`, `keyword` FROM " . tablename('qrcode') . " WHERE {$scene_condition} AND `uniacid` = :uniacid AND `type` = 'scene'", $condition_params);
  491. }
  492. if (empty($qr) && !empty($message['ticket'])) {
  493. $message['source'] = 'qr';
  494. $ticket = trim($message['ticket']);
  495. if(!empty($ticket)) {
  496. $qr = pdo_fetchall("SELECT `id`, `keyword` FROM " . tablename('qrcode') . " WHERE `uniacid` = :uniacid AND ticket = :ticket", array(':uniacid' => $_W['uniacid'], ':ticket' => $ticket));
  497. if(!empty($qr)) {
  498. if(count($qr) != 1) {
  499. $qr = array();
  500. } else {
  501. $qr = $qr[0];
  502. }
  503. }
  504. }
  505. }
  506. if(!empty($qr)) {
  507. $message['content'] = $qr['keyword'];
  508. if (!empty($qr['type']) && $qr['type'] == 'scene') {
  509. $message['msgtype'] = 'text';
  510. }
  511. $params += $this->analyzeText($message);
  512. }
  513. if (empty($qr)) {
  514. $params = $this->handler($default_message['type']);
  515. if (!empty($params)) {
  516. $message = $default_message;
  517. return $params;
  518. }
  519. }
  520. if (empty($params)) {
  521. $params = $this->handler($message['type']);
  522. }
  523. return $params;
  524. }
  525. public function analyzeText(&$message, $order = 0) {
  526. global $_W;
  527. $pars = array();
  528. $order = intval($order);
  529. if(!isset($message['content'])) {
  530. return $pars;
  531. }
  532. $cachekey = cache_system_key('keyword', array('content' => md5($message['content']), 'uniacid' => $_W['uniacid']));
  533. $keyword_cache = cache_load($cachekey);
  534. if (!empty($keyword_cache) && $keyword_cache['expire'] > TIMESTAMP) {
  535. foreach ($keyword_cache['data'] as $key => &$value) {
  536. $value['message'] = $message;
  537. }
  538. unset($value);
  539. return $keyword_cache['data'];
  540. }
  541. $condition = <<<EOF
  542. `uniacid` IN ( 0, {$_W['uniacid']} )
  543. AND
  544. (
  545. ( `type` = 1 AND `content` = :c1 )
  546. or
  547. ( `type` = 2 AND instr(:c2, `content`) )
  548. or
  549. ( `type` = 3 AND :c3 REGEXP `content` )
  550. or
  551. ( `type` = 4 )
  552. )
  553. AND `status`=1
  554. EOF;
  555. $params = array();
  556. $params[':c1'] = $message['content'];
  557. $params[':c2'] = $message['content'];
  558. $params[':c3'] = $message['content'];
  559. if (intval($order) > 0) {
  560. $condition .= " AND `displayorder` > :order";
  561. $params[':order'] = $order;
  562. }
  563. $keywords = reply_keywords_search($condition, $params);
  564. if(empty($keywords)) {
  565. return $pars;
  566. }
  567. $system_module_reply = true;
  568. foreach($keywords as $keyword) {
  569. if (!in_array($keyword['module'], array('defalut', 'cover', 'reply'))) {
  570. $system_module_reply = false;
  571. }
  572. $params = array(
  573. 'message' => $message,
  574. 'module' => $keyword['module'],
  575. 'rule' => $keyword['rid'],
  576. 'priority' => $keyword['displayorder'],
  577. 'keyword' => $keyword,
  578. 'reply_type' => $keyword['reply_type']
  579. );
  580. $pars[] = $params;
  581. }
  582. if (!empty($system_module_reply)) {
  583. $cache = array(
  584. 'data' => $pars,
  585. 'expire' => TIMESTAMP + 5 * 60,
  586. );
  587. cache_write($cachekey, $cache);
  588. }
  589. return $pars;
  590. }
  591. private function analyzeEvent(&$message) {
  592. if (strtolower($message['event']) == 'subscribe') {
  593. return $this->analyzeSubscribe($message);
  594. }
  595. if (strtolower($message['event']) == 'click') {
  596. $message['content'] = strval($message['eventkey']);
  597. return $this->analyzeClick($message);
  598. }
  599. if (in_array($message['event'], array('pic_photo_or_album', 'pic_weixin', 'pic_sysphoto'))) {
  600. pdo_delete('menu_event', array('createtime <' => $GLOBALS['_W']['timestamp'] - 100, 'openid' => $message['from']), 'OR');
  601. if (!empty($message['sendpicsinfo']['count'])) {
  602. foreach ($message['sendpicsinfo']['piclist'] as $item) {
  603. pdo_insert('menu_event', array(
  604. 'uniacid' => $GLOBALS['_W']['uniacid'],
  605. 'keyword' => $message['eventkey'],
  606. 'type' => $message['event'],
  607. 'picmd5' => $item,
  608. 'openid' => $message['from'],
  609. 'createtime' => TIMESTAMP,
  610. ));
  611. }
  612. } else {
  613. pdo_insert('menu_event', array(
  614. 'uniacid' => $GLOBALS['_W']['uniacid'],
  615. 'keyword' => $message['eventkey'],
  616. 'type' => $message['event'],
  617. 'picmd5' => $item,
  618. 'openid' => $message['from'],
  619. 'createtime' => TIMESTAMP,
  620. ));
  621. }
  622. $message['content'] = strval($message['eventkey']);
  623. $message['source'] = $message['event'];
  624. return $this->analyzeText($message);
  625. }
  626. if (!empty($message['eventkey'])) {
  627. $message['content'] = strval($message['eventkey']);
  628. $message['type'] = 'text';
  629. $message['redirection'] = true;
  630. $message['source'] = $message['event'];
  631. return $this->analyzeText($message);
  632. }
  633. return $this->handler($message['event']);
  634. }
  635. private function analyzeClick(&$message) {
  636. if(!empty($message['content']) || $message['content'] !== '') {
  637. $message['type'] = 'text';
  638. $message['redirection'] = true;
  639. $message['source'] = 'click';
  640. return $this->analyzeText($message);
  641. }
  642. return array();
  643. }
  644. private function analyzeImage(&$message) {
  645. load()->func('communication');
  646. if (!empty($message['picurl'])) {
  647. $response = ihttp_get($message['picurl']);
  648. if (!empty($response)) {
  649. $md5 = md5($response['content']);
  650. $event = pdo_get('menu_event', array('picmd5' => $md5), array('keyword', 'type'));
  651. if (!empty($event['keyword'])) {
  652. pdo_delete('menu_event', array('picmd5' => $md5));
  653. } else {
  654. $event = pdo_get('menu_event', array('openid' => $message['from']), array('keyword', 'type'));
  655. }
  656. if (!empty($event)) {
  657. $message['content'] = $event['keyword'];
  658. $message['eventkey'] = $event['keyword'];
  659. $message['type'] = 'text';
  660. $message['event'] = $event['type'];
  661. $message['redirection'] = true;
  662. $message['source'] = $event['type'];
  663. return $this->analyzeText($message);
  664. }
  665. }
  666. return $this->handler('image');
  667. }
  668. }
  669. private function analyzeVoice(&$message) {
  670. $params = $this->handler('voice');
  671. if (empty($params) && !empty($message['recognition'])) {
  672. $message['type'] = 'text';
  673. $message['redirection'] = true;
  674. $message['source'] = 'voice';
  675. $message['content'] = $message['recognition'];
  676. return $this->analyzeText($message);
  677. } else {
  678. return $params;
  679. }
  680. }
  681. private function handler($type) {
  682. if(empty($type)) {
  683. return array();
  684. }
  685. global $_W;
  686. $params = array();
  687. $setting = uni_setting($_W['uniacid'], array('default_message'));
  688. $default_message = $setting['default_message'];
  689. if(is_array($default_message) && !empty($default_message[$type]['type'])) {
  690. if ($default_message[$type]['type'] == 'keyword') {
  691. $message = $this->message;
  692. $message['type'] = 'text';
  693. $message['redirection'] = true;
  694. $message['source'] = $type;
  695. $message['content'] = $default_message[$type]['keyword'];
  696. return $this->analyzeText($message);
  697. } else {
  698. $params[] = array(
  699. 'message' => $this->message,
  700. 'module' => is_array($default_message[$type]) ? $default_message[$type]['module'] : $default_message[$type],
  701. 'rule' => '-1',
  702. );
  703. return $params;
  704. }
  705. }
  706. return array();
  707. }
  708. private function process($param) {
  709. global $_W;
  710. if(empty($param['module']) || !in_array($param['module'], $this->modules)) {
  711. return false;
  712. }
  713. if ($param['module'] == 'reply') {
  714. $processor = WeUtility::createModuleProcessor('core');
  715. } else {
  716. $processor = WeUtility::createModuleProcessor($param['module']);
  717. }
  718. $processor->message = $param['message'];
  719. $processor->rule = $param['rule'];
  720. $processor->reply_type = $param['reply_type'];
  721. $processor->priority = intval($param['priority']);
  722. $processor->inContext = $param['context'] === true;
  723. $response = $processor->respond();
  724. if(empty($response)) {
  725. return false;
  726. }
  727. return $response;
  728. }
  729. public function died($content = '') {
  730. global $_W, $engine;
  731. if (empty($content)) {
  732. exit('');
  733. }
  734. $response['FromUserName'] = $engine->message['to'];
  735. $response['ToUserName'] = $engine->message['from'];
  736. $response['MsgType'] = 'text';
  737. $response['Content'] = htmlspecialchars_decode($content);
  738. $response['CreateTime'] = TIMESTAMP;
  739. $response['FuncFlag'] = 0;
  740. $xml = array2xml($response);
  741. if(!empty($_GET['encrypt_type']) && $_GET['encrypt_type'] == 'aes') {
  742. $resp = $engine->account->encryptMsg($xml);
  743. $resp = $engine->account->xmlDetract($resp);
  744. } else {
  745. $resp = $xml;
  746. }
  747. exit($resp);
  748. }
  749. }