PageRenderTime 84ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/controller/api.class.php

https://github.com/nigelbaor/TeamToy
PHP | 2847 lines | 1587 code | 611 blank | 649 comment | 449 complexity | 954cd926360ca611ed4d81755197b24d MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. if( !defined('IN') ) die('bad request');
  3. include_once( AROOT . 'controller'.DS.'app.class.php' );
  4. define( 'LR_API_TOKEN_ERROR' , 10001 );
  5. define( 'LR_API_USER_ERROR' , 10002 );
  6. define( 'LR_API_DB_ERROR' , 10004 );
  7. define( 'LR_API_NOT_IMPLEMENT_YET' , 10005 );
  8. define( 'LR_API_ARGS_ERROR' , 10006 );
  9. define( 'LR_API_DB_EMPTY_RESULT' , 10007 );
  10. define( 'LR_API_USER_CLOSED' , 10008 );
  11. define( 'LR_API_FORBIDDEN' , 10009 );
  12. define( 'LR_API_UPGRADE_ERROR' , 10010 );
  13. define( 'LR_API_UPGRADE_ABORT' , 10011 );
  14. /**
  15. * TeamToy Open Api
  16. *
  17. * @author easychen
  18. * @version $Id$
  19. * @package server
  20. *
  21. */
  22. /**
  23. * apiController class
  24. * TeamToy OpenAPI实现
  25. *
  26. * <code>
  27. * <?php
  28. * $api_url = 'http://api.teamtoy.net/index.php';
  29. * $info = json_decode(file_get_contents( $api_url . '?c=api&a=user_get_token&password=******&email=abc@qq.com' ) , 1);
  30. * $token = $info['data']['token'];
  31. *
  32. * $todos = json_decode(file_get_contents( $api_url . '?c=api&a=todo_list&token=' . $token ) , 1);
  33. * print_r( $todos );
  34. *
  35. *
  36. * ?>
  37. * </code>
  38. *
  39. *
  40. * @author easychen
  41. * @package server
  42. *
  43. */
  44. class apiController extends appController
  45. {
  46. function __construct()
  47. {
  48. parent :: __construct();
  49. apply_filter( 'API_' . g('a') .'_INPUT_FILTER' );
  50. $not_check = array( 'user_sign_up' , 'user_get_token' );
  51. $not_check = apply_filter('API_LOGIN_ACTION_FILTER' , $not_check );
  52. if( !in_array( g('a') , $not_check )) $this->check_token();
  53. }
  54. public function __call( $method , $args)
  55. {
  56. // 进入这里表示不存在当前调用的api(no public method)
  57. return do_action( 'API_' . $method , $args );
  58. }
  59. /**
  60. * 用户注册
  61. *
  62. * 只有以管理员的token才能注册用户,否则需要激活码
  63. *
  64. * @param string name
  65. * @param string email
  66. * @param string password
  67. * @return user array
  68. * @author EasyChen
  69. */
  70. public function user_sign_up()
  71. {
  72. if( !not_empty( v( 'name' ) )) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'NAME' ) );
  73. if( !is_email( v( 'email' ) ) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_EMAIL') );
  74. if( strlen( v( 'password' ) ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'PASSWORD' ) );// actions
  75. // admin add user derictly
  76. $jump = false;
  77. $token = z( t( v( 'token' ) ) );
  78. if( strlen( $token ) > 2 )
  79. {
  80. session_id( $token );
  81. session_set_cookie_params( c('session_time') );
  82. @session_start();
  83. if($_SESSION['level'] == '9') $jump = true;
  84. }
  85. if( !$jump )
  86. {
  87. if( !not_empty( v( 'code' ) )) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'CODE' ) );
  88. $code = z(t(v('code')));
  89. if( get_var( "SELECT COUNT(*) FROM `activecode` WHERE `code` = '" . s($code) . "' AND `timeline` > '" . date( "Y-m-d H:i:s " , strtotime("-1day")) . "'" ) < 1 )
  90. return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ACTVECODE') );
  91. }
  92. if( get_var("SELECT COUNT(*) FROM `user` WHERE `email` = '" . s( t(v('email')) ) . "'") > 0 )
  93. return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_EMAIL_EXISTS') );
  94. $dsql = array();
  95. $dsql[] = "'" . s( v( 'name' ) ) . "'";
  96. $dsql[] = "'" . s( pinyin(strtolower(v( 'name' ))) ) . "'";
  97. $dsql[] = "'" . s( v( 'email' ) ) . "'";
  98. $dsql[] = "'" . s( md5( v( 'password' ) ) ) . "'";
  99. $dsql[] = "'" . s( date( "Y-m-d H:i:s" ) ) . "'";
  100. $sql = "INSERT INTO `user` ( `name` , `pinyin` , `email` , `password` , `timeline` ) VALUES ( " . join( ' , ' , $dsql ) . " )";
  101. run_sql( $sql );
  102. if( db_errno() != 0 )
  103. {
  104. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  105. }
  106. $lid = last_id();
  107. if( $lid < 1 )
  108. {
  109. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  110. }
  111. if( !$data = get_user_info_by_id( $lid ) )
  112. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  113. else
  114. {
  115. // one code for multi-people
  116. /*
  117. $sql = "DELETE FROM `activecode` WHERE `code` = '" . s($code) . "' LIMIT 1";
  118. run_sql( $sql );
  119. */
  120. publish_feed( __( 'API_TEXT_JOINT_TEAMTOY' , $data['name'] ) , $data['uid'] , 3 );
  121. return self::send_result( $data );
  122. }
  123. }
  124. /**
  125. * 更新当前用户分组
  126. *
  127. * @param string uid
  128. * @param string groups , 多个group用|分割
  129. * @param string token , 必填
  130. * @return user array
  131. * @author EasyChen
  132. */
  133. public function user_update_groups()
  134. {
  135. // 管理员权限
  136. if( $_SESSION['level'] != '9' )
  137. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_ONLY_ADMIN') );
  138. $uid = intval(v('uid'));
  139. if( $uid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'UID' ) );
  140. $groups = strtoupper(z(t(v('groups'))));
  141. if( strlen( $groups ) > 0 )
  142. $groups = '|' . trim( $groups , '|' ) . '|';
  143. $sql = "UPDATE `user` SET `groups` = '" . s( $groups ) . "' WHERE `id` = '" . intval($uid) . "' LIMIT 1";
  144. run_sql( $sql );
  145. if( db_errno() != 0 )
  146. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  147. else
  148. return self::send_result( get_user_info_by_id($uid) );
  149. }
  150. /**
  151. * 终止当前token
  152. *
  153. *
  154. * @param string token , 必填
  155. * @return user array
  156. * @author EasyChen
  157. */
  158. public function user_end_session()
  159. {
  160. $data = array();
  161. $data['token'] = $_SESSION['token'];
  162. $data['uid'] = $_SESSION['uid'];
  163. foreach( $_SESSION as $key=>$value )
  164. {
  165. unset( $_SESSION[$key] );
  166. }
  167. session_destroy();
  168. return self::send_result( $data );
  169. }
  170. /**
  171. * 检查是否存在新版本
  172. *
  173. *
  174. * @param string token , 必填
  175. * @return info array ( 'new' , 'version' , 'info' )
  176. * @author EasyChen
  177. */
  178. public function check_new_verison( $in = false )
  179. {
  180. $last = intval(kget('last_check'));
  181. if( $last > 0 && ( (time()-$last) < 60*60 ) && $in )
  182. {
  183. // checked in 1 hour
  184. // do nothing
  185. }
  186. else
  187. {
  188. // set timeout
  189. $ctx=stream_context_create(array('http'=>array( 'timeout' => 3 )));
  190. // send domain and uid to help teamtoy.net anti-cc attack
  191. $url = c('teamtoy_url') . '/?a=last_version&domain=' . c('site_domain') . '&uid=' . $user[ 'id' ];
  192. if( c('dev_version') ) $url = $url . '&dev=1';
  193. $new = false;
  194. if($info = @file_get_contents($url , 0 , $ctx))
  195. {
  196. $info_array = json_decode($info,true);
  197. if( $new_build = intval($info_array['version']) )
  198. {
  199. if( $new_build > local_version() )
  200. {
  201. $new = true;
  202. $last_noticed_version = intval(kget('last_notice'));
  203. if( $last_noticed_version > 0 )
  204. {
  205. if( $new_build > $last_noticed_version )
  206. $send = 1;
  207. else
  208. $send = 0;
  209. }
  210. else
  211. $send = 1;
  212. if( $send == 1 )
  213. {
  214. // send notice to current user
  215. $text = __( 'API_TEXT_NEW_VERSION' , $new_build );
  216. if( !$in )
  217. {
  218. send_notice( uid() , $text , 10 , array( 'info' => $info_array['desp'] ) );
  219. kset('last_notice',$new_build);
  220. }
  221. }
  222. }
  223. kset('last_check',time());
  224. }
  225. }
  226. if( !$in )
  227. {
  228. if( $new )
  229. return self::send_result( array('new'=>1 ,'info' => $info_array['desp'] , 'version' => $info_array['version'] ) );
  230. else
  231. return self::send_result( array('new'=>0 ) );
  232. }
  233. }
  234. }
  235. /**
  236. * 通过email和密码获取token
  237. *
  238. * @param string email
  239. * @param string password
  240. * @return token array( 'token' , 'uid' , 'uname' , 'email' , 'level' )
  241. * @author EasyChen
  242. */
  243. public function user_get_token()
  244. {
  245. $email = z( t( v( 'email' ) ) );
  246. $password = z( t( v( 'password' ) ) );
  247. if( $user = get_full_info_by_email_password( $email , $password ) )
  248. {
  249. if( $user['is_closed'] == '1' )
  250. return self::send_error( LR_API_USER_CLOSED , __('API_MESSAGE_USER_CLOSED_BY_ADMIN') );
  251. session_set_cookie_params( c('session_time') );
  252. @session_start();
  253. $token = session_id();
  254. $_SESSION[ 'token' ] = $token;
  255. $_SESSION[ 'uid' ] = $user[ 'id' ];
  256. $_SESSION[ 'uname' ] = $user['name'];
  257. $_SESSION[ 'email' ] = $user[ 'email' ];
  258. $_SESSION[ 'level' ] = $user['level'];
  259. if( strlen( $user['groups'] ) > 0 )
  260. {
  261. $user['groups'] = explode('|', trim( $user['groups'] , '|' )) ;
  262. $_SESSION[ 'groups' ] = $user['groups'];
  263. }
  264. if( c('api_check_new_verison') )
  265. $this->check_new_verison( true );
  266. return self::send_result( $_SESSION );
  267. }
  268. else
  269. {
  270. return self::send_error( LR_API_TOKEN_ERROR , __('API_MESSAGE_BAD_ACCOUNT') );
  271. }
  272. }
  273. /**
  274. * 重置密码
  275. *
  276. * 只有管理员token才能调用
  277. *
  278. * @param string token , 必填
  279. * @param string uid
  280. * @return msg array( 'newpass'=>newpass )
  281. * @author EasyChen
  282. */
  283. function user_reset_password()
  284. {
  285. if( $_SESSION['level'] != '9' )
  286. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_ONLY_ADMIN') );
  287. $uid = intval(v('uid'));
  288. if( $uid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'UID' ) );
  289. if( $uid == uid() ) return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_CANNOT_RESET_OWN_PASSWORD') );
  290. $rnd = rand( 1 , 10 );
  291. $newpass = substr( md5($uid.time().rand( 1 , 9999 )) , $rnd , 15 );
  292. $sql = "UPDATE `user` SET `password` = '". md5($newpass)."' WHERE `id` = '" . intval( $uid ) . "' LIMIT 1";
  293. run_sql( $sql );
  294. if( db_errno() != 0 )
  295. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  296. else
  297. return self::send_result( array( 'newpass' => $newpass ) );
  298. }
  299. /**
  300. * 在线升级
  301. *
  302. * 只有管理员token才能调用
  303. *
  304. * @param string token , 必填
  305. * @param string password
  306. * @return msg array( 'msg'=>ok )
  307. * @author EasyChen
  308. */
  309. function upgrade()
  310. {
  311. if( $_SESSION['level'] != '9' )
  312. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_ONLY_ADMIN') );
  313. $url = c('teamtoy_url') . '/?a=last_version&domain=' . c('site_domain') . '&uid=' . uid();
  314. if( c('dev_version') ) $url = $url . '&dev=1';
  315. $info = json_decode( file_get_contents( $url ) , true);
  316. if( !isset($info['url']) ) return self::send_error( LR_API_UPGRADE_ERROR , __('API_MESSAGE_UPGARDE_INFO_DATA_ERROR') );
  317. $url = t($info['url']);
  318. $vid = intval($info['version']);
  319. if( $vid < 1 ) return self::send_error( LR_API_UPGRADE_ERROR , __('API_MESSAGE_UPGARDE_INFO_DATA_ERROR') );
  320. if( $vid == local_version() )
  321. {
  322. return self::send_error( LR_API_UPGRADE_ABORT , __('API_MESSAGE_UPGARDE_ALREADY_LATEST') );
  323. }
  324. $zip_tmp = SAE_TMP_PATH . DS . 'teamtoy2-' . intval($vid) . '.zip';
  325. if( @copy( $url , $zip_tmp ) )
  326. {
  327. include_once( AROOT.'lib'.DS.'dUnzip2.inc.php' );
  328. $zip = new dUnzip2( $zip_tmp );
  329. $zip->debug = false;
  330. $zip->unzipAll( AROOT );
  331. @chmod( AROOT , 0755 );
  332. if( isset( $info['post_script'] ) ) $pscript = t($info['post_script']);
  333. else $pscript = false;
  334. if( local_version() == $vid )
  335. {
  336. if( $pscript )
  337. send_notice( uid() , __('API_TEXT_ALREADY_UPGARDE_TO' , array ( $vid , c('site_url') . $pscript) ), 0 );
  338. return self::send_result( array('msg'=>'ok','post_script'=>$pscript) );
  339. }
  340. else
  341. return self::send_error( LR_API_UPGRADE_ERROR , __('API_MESSAGE_UPGARDE_FILE_UNZIP_ERROR') );
  342. }
  343. else
  344. {
  345. return self::send_error( LR_API_UPGRADE_ERROR , __('API_MESSAGE_UPGARDE_FILE_FETCH_ERROR') );
  346. }
  347. }
  348. /**
  349. * 读取用户个人资料
  350. *
  351. * 不包含密码
  352. *
  353. * @param string token , 必填
  354. * @param int uid
  355. * @return user array
  356. * @author EasyChen
  357. */
  358. function user_profile()
  359. {
  360. $uid = intval(v('uid'));
  361. if( $uid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'UID' ) );
  362. return self::send_result( get_user_info_by_id($uid) );
  363. }
  364. /**
  365. * 更新用户个人资料
  366. *
  367. * 不包含密码
  368. *
  369. * @param string token , 必填
  370. * @param string mobile - 手机号 , 必填
  371. * @param string email - 电子邮件 , 必填
  372. * @param string tel - 分机号 , 选填
  373. * @param string eid - 工号, 选填
  374. * @param string weibo - 微博昵称, 选填
  375. * @param string desp - 备注, 选填
  376. * @return user array
  377. * @author EasyChen
  378. */
  379. function user_update_profile()
  380. {
  381. $mobile = z(t(v('mobile')));
  382. $tel = z(t(v('tel')));
  383. $eid = z(t(v('eid')));
  384. $weibo = z(t(v('weibo')));
  385. $desp = z(t(v('desp')));
  386. $email = z(t(v('email')));
  387. if( !not_empty($email) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'EMAIL' ) );
  388. if( !not_empty($mobile) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'MOBILE' ) );
  389. $sql = "UPDATE `user` SET "
  390. ." `mobile` = '" . s($mobile) . "' "
  391. ." , `tel` = '" . s($tel) . "' "
  392. ." , `eid` = '" . s($eid) . "' "
  393. ." , `weibo` = '" . s($weibo) . "' "
  394. ." , `email` = '" . s($email) . "' "
  395. ." , `desp` = '" . s($desp) . "' WHERE `id` = '" . uid() . "' LIMIT 1 ";
  396. run_sql( $sql );
  397. if( db_errno() != 0 )
  398. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  399. else
  400. return self::send_result( get_user_info_by_id(uid()) );
  401. }
  402. /**
  403. * 读取用户扩展设置
  404. *
  405. * @ignore
  406. */
  407. function user_settings()
  408. {
  409. if(!is_array( $settings = get_user_settings_by_id( $_SESSION['uid'] ) ))
  410. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_FETCH_SETTINGS_DATA_ERROR') );
  411. else
  412. return self::send_result( $settings );
  413. }
  414. /**
  415. * 更新用户密码
  416. *
  417. *
  418. * @param string token , 必填
  419. * @param string opassword - 原密码 , 必填
  420. * @param string password -新密码 , 必填
  421. * @return msg array( 'msg'=>ok )
  422. * @author EasyChen
  423. */
  424. function user_update_password()
  425. {
  426. if( !c('can_modify_password') ) return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_CANNOT_CHANGE_PASSWORD') );
  427. $opassword = z(t(v('opassword')));
  428. if( !not_empty($opassword) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'OPASSWORD' ) );
  429. $password = z(t(v('password')));
  430. if( !not_empty($password) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'PASSWORD' ) );
  431. if( $opassword == $password ) return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_SAME_PASSWORD') );
  432. $passwordv1 = md5( $opassword );
  433. $passwordv2 = ttpassv2( $opassword , uid() );
  434. $sql = "SELECT COUNT(*) FROM `user` WHERE `id` = '" . intval( uid() ) . "' AND ( `password` = '" . s($passwordv1) . "' OR `password` = '" . s($passwordv2) . "' ) ";
  435. if( get_var( $sql ) < 1 )
  436. return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_BAD_OPASSWORD') );
  437. $newpass = ttpassv2( $password , uid() );
  438. $sql = "UPDATE `user` SET `password` = '" . s($newpass) . "' WHERE `id` = '" . intval( uid() ) . "' AND ( `password` = '" . s($passwordv1) . "' OR `password` = '" . s($passwordv2) . "' ) LIMIT 1";
  439. run_sql( $sql );
  440. if( db_errno() != 0 )
  441. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  442. else
  443. return self::send_result( array('msg'=>'ok') );
  444. }
  445. /**
  446. * 更新用户扩展设置
  447. *
  448. * @ignore
  449. */
  450. function user_update_settings()
  451. {
  452. $key = z(t(v('key')));
  453. if( !not_empty($key) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'KEY' ) );
  454. if(!$value = unserialize(v('value')))
  455. {
  456. $value = z(t(v('value')));
  457. if( !not_empty($value) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'VALUE' ) );
  458. }
  459. else
  460. {
  461. if( !is_array($value) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'VALUE' ) );
  462. }
  463. if(!is_array( $settings = get_user_settings_by_id( $_SESSION['uid'] ) ))
  464. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_FETCH_SETTINGS_DATA_ERROR') );
  465. else
  466. {
  467. $settings[$key] = $value;
  468. update_user_settings_array( $settings );
  469. if( db_errno() != 0 )
  470. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  471. else
  472. return self::send_result( $settings );
  473. }
  474. }
  475. /**
  476. * 更新用户等级
  477. *
  478. * 必须是管理员的token,level9为管理员,不能修改自己的等级
  479. *
  480. * @param string token , 必填
  481. * @param string uid , 必填
  482. * @return user array
  483. * @author EasyChen
  484. */
  485. function user_level()
  486. {
  487. $uid = intval(v('uid'));
  488. if( $uid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'UID' ) );
  489. if( $uid == uid() ) return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_CANNOT_CHANGE_OWN_LEVEL') );
  490. if(!$user = get_user_info_by_id( $uid ))
  491. return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_USER_NOT_EXISTS') );
  492. $level = intval(v('level'));
  493. if( $_SESSION['level'] != '9' )
  494. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_ONLY_ADMIN') );
  495. if( $level == 0 ) $more = " , `is_closed` = 1 ";
  496. else $more = "";
  497. $sql = "UPDATE `user` SET `level` = '" . intval( $level ) . "' " . $more . " WHERE `id` = '" . intval($uid) . "' LIMIT 1";
  498. run_sql( $sql );
  499. if( db_errno() != 0 )
  500. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  501. else
  502. {
  503. if( $level == 0 )
  504. {
  505. publish_feed( __('API_MESSAGE_ACCOUNT_CLOSED' , array( uname() , $user['name'] ) ) , uid() , 1 );
  506. $user['level'] = 0;
  507. return self::send_result( $user );
  508. }
  509. else
  510. {
  511. // uname().'修改了账号【'. $user['name'] .'】权限为'.$level
  512. if( $level == 0 ) $level_text = __('ACCOUNT_CLOSED');
  513. elseif( $level == 9 ) $level_text = __('ACCOUNT_SUPER_ADMIN');
  514. else $level_text = $level;
  515. publish_feed( __('API_MESSAGE_USER_LEVEL_UPDATED' , array( uname() , $user['name'] , $level_text ) ) , uid() , 1 );
  516. return self::send_result( get_user_info_by_id($uid) );
  517. }
  518. }
  519. }
  520. /**
  521. * 关闭用户
  522. *
  523. * 必须是管理员的token
  524. *
  525. * @param string token , 必填
  526. * @param string uid , 必填
  527. * @return user array
  528. * @author EasyChen
  529. */
  530. function user_close()
  531. {
  532. $uid = intval(v('uid'));
  533. if( $uid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'UID' ) );
  534. if(!$user = get_user_info_by_id( $uid ))
  535. return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_USER_NOT_EXISTS') );
  536. if( $_SESSION['level'] != '9' )
  537. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_ONLY_ADMIN') );
  538. if( $user['is_closed'] == '1' )
  539. return self::send_error( LR_API_USER_CLOSED , __('API_MESSAGE_USER_CLOSED_BY_ADMIN') );
  540. if( $_SESSION['level'] == '9' && $uid == uid() )
  541. {
  542. $admin_num = get_var( "SELECT COUNT(*) FROM `user` WHERE `is_closed` = 0 AND `level` = 9 " );
  543. if( $admin_num < 2 ) return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_CLOSE_ONLY_ADMIN') );
  544. }
  545. close_user_by_id($uid);
  546. if( db_errno() != 0 )
  547. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  548. else
  549. {
  550. publish_feed( __('API_MESSAGE_ACCOUNT_CLOSED' , array( uname() , $user['name'] ) ) , uid() , 1 );
  551. return self::send_result( $user );
  552. }
  553. }
  554. /**
  555. * 添加TODO
  556. *
  557. *
  558. * @param string token , 必填
  559. * @param string text - TODO内容 , 必填
  560. * @param string is_public - 是否公开 , 默认为1
  561. * @param string uid - 要给添加TODO的用户id , uid为0时添加给自己。私有TODO不能添加给其他人
  562. * @return todo array
  563. * @author EasyChen
  564. */
  565. public function todo_add()
  566. {
  567. $content = z(t(v('text')));
  568. if( !not_empty($content) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'TEXT' ) );
  569. $is_public = intval(v('is_public'));
  570. if( $is_public != 0 ) $is_public = 1;
  571. $uid = intval(v('uid'));
  572. $owner_uid=$uid>0?$uid:uid();
  573. // 检查是否已经存在
  574. $sql = "SELECT * FROM `todo` WHERE `content` = '" . s( $content ) . "' AND `owner_uid` = '" . intval($owner_uid) . "' LIMIT 1";
  575. if( $todo = get_line($sql) )
  576. {
  577. if( get_var( "SELECT COUNT(*) FROM `todo_user` WHERE `tid` = '" . intval( $todo['id'] ) . "' AND `uid` = '" . intval( $owner_uid ) . "' AND `status` != 3 " ) > 0 )
  578. return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_TODO_EXISTS') );
  579. }
  580. if( !$tid = add_todo( $content , $is_public ))
  581. {
  582. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  583. }
  584. $tinfo = get_todo_info_by_id( $tid );
  585. if( $is_public == 1 )
  586. {
  587. if( $uid > 0 && $uid !=uid() )
  588. {
  589. $this->todo_assign( $tid , $uid , true );
  590. $tinfo['other'] = 1;
  591. }
  592. else
  593. publish_feed( __('API_TEXT_TODO_ADDED' , array( uname() , $content ) ) , uid() , 2 , $tid );
  594. // .'添加了TODO【'. .'】'
  595. }
  596. return self::send_result( $tinfo );
  597. }
  598. /**
  599. * 删除TODO评论
  600. *
  601. *
  602. * @param string token , 必填
  603. * @param string hid - 评论id, 必填
  604. * @return comment array
  605. * @author EasyChen
  606. */
  607. public function todo_remove_comment()
  608. {
  609. $hid = intval(v('hid'));
  610. if( intval( $hid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'HID') );
  611. $sql = "SELECT *,`id` as `hid` FROM `todo_history` WHERE `id` = '" . intval( $hid ) . "' LIMIT 1";
  612. if( !$hitem = get_line( $sql ) )
  613. {
  614. if( db_errno() != 0 )
  615. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  616. else
  617. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  618. }
  619. else
  620. {
  621. if( ($hitem['uid'] != $_SESSION['uid']) && $_SESSION['level'] < 9 )
  622. {
  623. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_REMOVE_OTHERS_COMMENT') );
  624. }
  625. if( $hitem['type'] != 2 )
  626. {
  627. return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_HTYPE') );
  628. }
  629. $sql = "DELETE FROM `todo_history` WHERE `id` = '" . intval($hid) . "' LIMIT 1";
  630. run_sql( $sql );
  631. if( db_errno() != 0 )
  632. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  633. else
  634. {
  635. // 更新todo 评论计数
  636. $tid = $hitem['tid'];
  637. $count = get_var( "SELECT COUNT(*) FROM `todo_history` WHERE `tid` = '" . intval($tid) . "' AND `type` = 2 " , db()) ;
  638. $sql = "UPDATE `todo` SET `comment_count` = '" . intval($count) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  639. run_sql( $sql );
  640. $sql = "UPDATE `feed` SET `comment_count` = '" . intval( $count ) . "' WHERE `tid` = '" . intval( $tid ) . "' AND `comment_count` != '" . intval( $count ) . "' ";
  641. run_sql( $sql );
  642. return self::send_result( $hitem );
  643. }
  644. }
  645. }
  646. /**
  647. * 为TODO添加评论
  648. *
  649. *
  650. * @param string token , 必填
  651. * @param string tid - TODOid, 必填
  652. * @param string text - 评论内容, 必填
  653. * @return comment array
  654. * @author EasyChen
  655. */
  656. public function todo_add_comment()
  657. {
  658. $content = z(t(v('text')));
  659. if( !not_empty($content) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'TEXT') );
  660. $tid = intval(v('tid'));
  661. if( intval( $tid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'TID') );
  662. $tinfo = get_line("SELECT * FROM `todo` WHERE `id` = '" . intval( $tid ) . "' LIMIT 1");
  663. if( is_mobile_request() ) $device = 'mobile';
  664. else $device = 'web';
  665. $sql = "INSERT INTO `todo_history` ( `tid` , `uid` , `content` , `type` , `timeline` , `device` )
  666. VALUES ( '" . intval($tid) . "' , '" . intval($_SESSION['uid']) . "' , '" . s( $content ) . "' , '2' , NOW() , '" . s($device) . "' ) ";
  667. run_sql( $sql );
  668. if( db_errno() != 0 )
  669. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  670. else
  671. {
  672. $lid = last_id();
  673. // 更新todo 评论计数
  674. $count = get_var( "SELECT COUNT(*) FROM `todo_history` WHERE `tid` = '" . intval($tid) . "' AND `type` = 2 " , db()) ;
  675. $sql = "UPDATE `todo` SET `comment_count` = '" . intval($count) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  676. run_sql( $sql );
  677. $sql = "UPDATE `feed` SET `comment_count` = '" . intval( $count ) . "' WHERE `tid` = '" . intval( $tid ) . "' AND `comment_count` != '" . intval( $count ) . "' ";
  678. run_sql( $sql );
  679. // 向订阅todo的同学发送通知
  680. $sql = "SELECT `uid` FROM `todo_user` WHERE `tid`= '" . intval($tid) . "' AND `is_follow` = 1 ";
  681. $follow_uids = array();
  682. if( $uitems = get_data( $sql ) )
  683. foreach( $uitems as $uitem )
  684. {
  685. if( $uitem['uid'] != uid() )
  686. {
  687. if( !in_array( $uitem['uid'] , $follow_uids ) )
  688. {
  689. // .'评论了你关注的TODO【'. $tinfo['content'] .'】: '.$content
  690. send_notice( $uitem['uid'] , __('API_TEXT_COMMENT_TODO_FOLLOWED' , array( uname() , $tinfo['content'] , $content ) ) , 1 , array('tid'=>intval($tid) , 'count' => $count ) );
  691. $follow_uids[] = $uitem['uid'];
  692. }
  693. }
  694. }
  695. // 向todo作者发通知
  696. if( $tinfo['owner_uid'] != uid() )
  697. {
  698. if( !in_array( $tinfo['owner_uid'] , $follow_uids ) )
  699. send_notice( $tinfo['owner_uid'] , __('API_TEXT_COMMENT_TODO_OWNED' , array( uname() , $tinfo['content'] , $content ) ) , 1 , array('tid'=>intval($tid) , 'count' => $count ) );
  700. }
  701. // 向被@的同学,发送通知
  702. if( $ats = find_at($content) )
  703. {
  704. $sql = "SELECT `id` FROM `user` WHERE ";
  705. foreach( $ats as $at )
  706. {
  707. $at =z(t($at));
  708. if( $gname = get_group_names() )
  709. {
  710. if( in_array(strtoupper($at),$gname) )
  711. {
  712. if( $ndata = get_group_unames($at) )
  713. foreach( $ndata as $nname )
  714. $names[] = $nname;
  715. }else $names[] = $at;
  716. }
  717. else
  718. {
  719. $names[] = $at;
  720. }
  721. }
  722. foreach( $names as $at )
  723. {
  724. $at =z(t($at));
  725. if( mb_strlen($at, 'UTF-8') < 2 ) continue;
  726. $wsql[] = " `name` = '" . s(t($at)) . "' ";
  727. if( c('at_short_name') )
  728. if( mb_strlen($at, 'UTF-8') == 2 )
  729. $wsql[] = " `name` LIKE '_" . s($at) . "' ";
  730. }
  731. if( isset( $wsql ) && is_array( $wsql ) )
  732. {
  733. $sql = $sql . join( ' OR ' , $wsql );
  734. if( $udata = get_data( $sql ) )
  735. foreach( $udata as $uitem )
  736. if( !in_array( $uitem['id'] , $follow_uids ) )
  737. $myuids[] = $uitem['id'];
  738. if( isset( $myuids ) && is_array($myuids) )
  739. {
  740. $myuids = array_unique($myuids);
  741. foreach( $myuids as $muid )
  742. {
  743. if( $muid != uid() && $muid != $tinfo['owner_uid'] )
  744. send_notice( $muid , __('API_TEXT_AT_IN_TODO_COMMENT' , array( uname() , $tinfo['content'] , $tinfo['content'] ) ) , 1 , array('tid'=>intval($tid) , 'count' => $count ));
  745. }
  746. }
  747. }
  748. }
  749. if( $comment = get_line( "SELECT * FROM `todo_history` WHERE `id` = '" . intval($lid) . "' LIMIT 1" , db() ) )
  750. {
  751. $comment['user'] = get_user_info_by_id( $_SESSION['uid'] );
  752. if($tinfo['is_public'] == 1)
  753. publish_feed( __('API_TEXT_COMMENT_TODO' , array( uname() , $tinfo['content'] , $tinfo['content'] ) ) , uid() , 2 , $tid );
  754. return self::send_result( $comment );
  755. }
  756. else
  757. {
  758. if( db_errno() != 0 )
  759. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  760. else
  761. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  762. }
  763. }
  764. }
  765. /**
  766. * 读取TODO详细信息
  767. *
  768. * 其他人的私有TODO会无法读取
  769. *
  770. * @param string token , 必填
  771. * @param string tid - TODOid, 必填
  772. * @return todo array
  773. * @author EasyChen
  774. */
  775. public function todo_detail()
  776. {
  777. $tid = intval(v('tid'));
  778. if( intval( $tid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'TID') );
  779. if( $tinfo = get_todo_info_by_id( $tid ) )
  780. {
  781. return self::send_result( $tinfo );
  782. }
  783. else
  784. {
  785. if( db_errno() != 0 )
  786. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  787. else
  788. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  789. }
  790. }
  791. /**
  792. * 指派TODO给其他人
  793. *
  794. * 不可以分配给自己
  795. *
  796. * @param string token , 必填
  797. * @param string tid - TODOid, 必填
  798. * @param string uid - 要指派的用户id, 必填
  799. * @return todo array
  800. * @author EasyChen
  801. */
  802. public function todo_assign( $tid = false , $uid = false , $in = false )
  803. {
  804. if( !$tid ) $tid = intval(v('tid'));
  805. if( intval( $tid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'TID') );
  806. if( !$uid ) $uid = intval(v('uid'));
  807. if( intval( $uid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS' , 'UID') );
  808. if( $uid == $_SESSION['uid'] ) return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_TODO_ASSIGN_TO_SELF') );
  809. if( !$tinfo = get_line( "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . uid() . "' LIMIT 1" ) )
  810. {
  811. if( db_errno() != 0 )
  812. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  813. else
  814. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  815. }
  816. else
  817. {
  818. if( $tinfo['uid'] != uid() ) return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_ASSIGN_OTHERS_TODO') );
  819. // 更新todo表
  820. $sql = "UPDATE `todo` SET `owner_uid` = '" . intval( $uid ) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  821. run_sql( $sql );
  822. if( db_errno() != 0 )
  823. if( $in )
  824. return false;
  825. else
  826. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  827. // 将新的uid加入 todo_user 表
  828. $sql = "REPLACE INTO `todo_user` ( `uid` , `tid` , `status` , `last_action_at` ) VALUES ( '" . intval( $uid ) . "' , '" . intval( $tid ) . "' , 1 , NOW() ) ";
  829. run_sql( $sql );
  830. if( db_errno() != 0 )
  831. if( $in )
  832. return false;
  833. else
  834. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  835. // 将现有uid 变为follow状态
  836. $sql = "UPDATE `todo_user` SET `is_follow` = 1 WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1";
  837. run_sql( $sql );
  838. if( db_errno() != 0 )
  839. if( $in )
  840. return false;
  841. else
  842. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  843. // 获取被转让人的信息
  844. $uinfo = get_user_info_by_id($uid);
  845. $todo_text = get_todo_text_by_id( $tid );
  846. $todo_count = get_var( "SELECT `comment_count` FROM `todo` WHERE `id` = '" . intval( $tid ) . "'" );
  847. // 向todo新主人发送通知
  848. send_notice( intval( $uid ) , __('API_TEXT_ASSIGN_TODO_TO_U',array( uname() , $todo_text )) , 1 , array('tid'=>intval($tid) , 'count'=> $todo_count ) );
  849. // 向todo关注者发送通知
  850. $sql = "SELECT `uid` FROM `todo_user` WHERE `tid`= '" . intval($tid) . "' AND `is_follow` = 1 ";
  851. if( $uitems = get_data( $sql ) )
  852. foreach( $uitems as $uitem )
  853. {
  854. // 避免向当前转让人发送通知
  855. if( $uitem['uid'] != uid() )
  856. send_notice( $uitem['uid'] , __('API_TEXT_ASSIGN_TODO_FOLLOWED' , array( uname() , $todo_text , $uinfo['name'] ) ) , 1 , array('tid'=>intval($tid) , 'count'=> $todo_count ) );
  857. }
  858. add_history( $tid , __('API_TEXT_ASSIGN_TODO') );
  859. publish_feed( __('API_TEXT_ASSIGN_TODO_DETAIL' , array( uname() , $todo_text , $uinfo['name'] ) ) , uid() , 2 , $tid );
  860. if( $in )
  861. return get_todo_info_by_id( $tid ) ;
  862. else
  863. return self::send_result( get_todo_info_by_id( $tid ) );
  864. }
  865. }
  866. /**
  867. * 获取TODO列表
  868. *
  869. *
  870. * @param string token , 必填
  871. * @param string since_id - 最小TODO id
  872. * @param string max_id - 最大TODO id
  873. * @param string count - 每页TODO条数
  874. * @param string ord - 排序 , asc 或者 desc
  875. * @param string by - 排序字段
  876. * @param string group - 按分组输出,默认为false
  877. * @return todo list array
  878. * @author EasyChen
  879. */
  880. public function todo_list()
  881. {
  882. $uid = intval(v('uid'));
  883. if( $uid < 1 ) $uid = $_SESSION['uid'];
  884. $since_id = intval( v( 'since_id' ) );
  885. $max_id = intval( v( 'max_id' ) );
  886. $count = intval( v( 'count' ) );
  887. $order = strtolower( z( t( v( 'ord' ) ) ) );
  888. $by = strtolower( z( t( v( 'by' ) ) ) );
  889. if( $order != 'desc' )
  890. $ord = ' ASC ';
  891. else
  892. $ord = ' DESC ';
  893. if( strlen( $by ) > 0 )
  894. {
  895. $osql = ' ORDER BY `' . s( $by ) . '` ' . $ord . ' ';
  896. }
  897. else
  898. $osql = '';
  899. if( $count < 1 ) $count = 10;
  900. if( $count > 100 ) $count = 100;
  901. if( $since_id > 0 )
  902. $wsql = " AND `tid` > '" . intval( $since_id ) . "' ";
  903. elseif( $max_id > 0 )
  904. $wsql = " AND `tid` < '" . intval( $max_id ) . "' ";
  905. else
  906. $wsql = '';
  907. if( $uid != uid() ) $wsql .= ' AND `is_public` = 1 ';
  908. $sql = "SELECT * FROM `todo_user` WHERE `uid` = '" . intval($uid) . "' ";
  909. $sql = $sql . $wsql . $osql . " LIMIT " . $count ;
  910. if( !$data = get_data( $sql ) ) return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  911. if( db_errno() != 0 )
  912. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') );
  913. $tids = array();
  914. foreach( $data as $item )
  915. {
  916. $tids[] = $item['tid'];
  917. $todos[$item['tid']] = $item;
  918. }
  919. if( count( $tids ) > 0 )
  920. {
  921. $sql = "SELECT * FROM `todo` WHERE `id` IN ( " . join( ' , ' , $tids ) . ") ORDER BY FIELD( `id` , " . join( ' , ' , $tids ) . " )";
  922. $todo = get_data( $sql );
  923. foreach( $todo as $t )
  924. {
  925. $todos[$t['id']]['uid'] = $t['owner_uid'];
  926. $todos[$t['id']]['content'] = $t['content'];
  927. $todos[$t['id']]['timeline'] = $t['timeline'];
  928. }
  929. // todo : sort it
  930. if( intval(v('group')) != 1 )
  931. return self::send_result(array_values($todos));
  932. else
  933. {
  934. $ret = Array();
  935. foreach( $todos as $tt )
  936. {
  937. if( $tt['is_follow'] ==1 )
  938. $ret['follow'][] = $tt;
  939. elseif( $tt['status'] == 3 )
  940. $ret['done'][] = $tt;
  941. elseif( $tt['is_star'] == 1 )
  942. $ret['star'][] = $tt;
  943. else
  944. $ret['normal'][] = $tt;
  945. }
  946. return self::send_result($ret);
  947. }
  948. }
  949. else
  950. {
  951. if( db_errno() != 0 )
  952. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  953. else
  954. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  955. }
  956. /*
  957. if( $data = get_user_todo_list_by_uid() )
  958. {
  959. return self::send_result( $data );
  960. }
  961. else
  962. {
  963. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  964. }*/
  965. }
  966. /**
  967. * TODO进行中
  968. *
  969. *
  970. * @param string token , 必填
  971. * @param string tid - TODO id , 必填
  972. * @return todo array
  973. * @author EasyChen
  974. */
  975. public function todo_start()
  976. {
  977. return $this->todo_set_value( 'status' , 2 );
  978. }
  979. /**
  980. * TODO暂停
  981. *
  982. *
  983. * @param string token , 必填
  984. * @param string tid - TODO id , 必填
  985. * @return todo array
  986. * @author EasyChen
  987. */
  988. public function todo_pause()
  989. {
  990. return $this->todo_set_value( 'status' , 1 );
  991. }
  992. /**
  993. * TODO加星
  994. *
  995. *
  996. * @param string token , 必填
  997. * @param string tid - TODO id , 必填
  998. * @return todo array
  999. * @author EasyChen
  1000. */
  1001. public function todo_star()
  1002. {
  1003. return $this->todo_set_value( 'is_star' , 1 );
  1004. }
  1005. /**
  1006. * TODO去星
  1007. *
  1008. *
  1009. * @param string token , 必填
  1010. * @param string tid - TODO id , 必填
  1011. * @return todo array
  1012. * @author EasyChen
  1013. */
  1014. public function todo_unstar()
  1015. {
  1016. return $this->todo_set_value( 'is_star' , 0 );
  1017. }
  1018. /**
  1019. * TODO设为公开
  1020. *
  1021. *
  1022. * @param string token , 必填
  1023. * @param string tid - TODO id , 必填
  1024. * @return todo array
  1025. * @author EasyChen
  1026. */
  1027. public function todo_public()
  1028. {
  1029. return $this->todo_set_value( 'is_public' , 1 );
  1030. }
  1031. /**
  1032. * TODO设为私密
  1033. *
  1034. *
  1035. * @param string token , 必填
  1036. * @param string tid - TODO id , 必填
  1037. * @return todo array
  1038. * @author EasyChen
  1039. */
  1040. public function todo_private()
  1041. {
  1042. return $this->todo_set_value( 'is_public' , 0 );
  1043. }
  1044. /**
  1045. * TODO设为已完成
  1046. *
  1047. *
  1048. * @param string token , 必填
  1049. * @param string tid - TODO id , 必填
  1050. * @return todo array
  1051. * @author EasyChen
  1052. */
  1053. public function todo_done()
  1054. {
  1055. return $this->todo_set_value( 'status' , 3 );
  1056. }
  1057. /**
  1058. * 重开TODO
  1059. *
  1060. *
  1061. * @param string token , 必填
  1062. * @param string tid - TODO id , 必填
  1063. * @return todo array
  1064. * @author EasyChen
  1065. */
  1066. public function todo_reopen()
  1067. {
  1068. return $this->todo_set_value( 'status' , 1 );
  1069. }
  1070. /**
  1071. * @ignore
  1072. */
  1073. private function todo_set_value( $field , $value )
  1074. {
  1075. $tid = intval(v('tid'));
  1076. if( $tid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TID') );
  1077. $sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1078. if( !$data = get_line( $sql ))
  1079. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_UPDATE_OTHERS_TODO') );
  1080. // delete uid and limit 1
  1081. // to make all record updated at sametime
  1082. // for all the followers
  1083. $sql = "UPDATE `todo_user` SET `" . s( $field ) . "` = '" . intval( $value ) . "' , `last_action_at` = NOW() WHERE `tid` = '" . intval( $tid ) . "' ";
  1084. run_sql( $sql );
  1085. if( mysql_errno() != 0 )
  1086. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1087. else
  1088. {
  1089. $todoinfo = get_todo_info_by_id( $tid , true );
  1090. kset('dinfo', $todoinfo['details']['is_public'] );
  1091. if( $field == 'status' && $value == 3 )
  1092. {
  1093. if( $todoinfo['details']['is_public'] == 1 )
  1094. {
  1095. // .'完成了TODO【'. .'】'
  1096. publish_feed( __('API_TEXT_FINISH_TODO' , array( uname() , $todoinfo['content'] ) ) , uid() , 2 , $tid );
  1097. // send notice
  1098. // 向订阅todo的同学发送通知
  1099. $sql = "SELECT `uid` FROM `todo_user` WHERE `tid`= '" . intval($tid) . "' AND `is_follow` = 1 ";
  1100. if( $uitems = get_data( $sql ) )
  1101. foreach( $uitems as $uitem )
  1102. {
  1103. if( $uitem['uid'] != uid() )
  1104. send_notice( $uitem['uid'] , __('API_TEXT_FINISH_TODO_FOLLOWED' , array( uname() , $todoinfo['content'] ) ) , 1 , array('tid'=>intval($tid) , 'count' => $todoinfo['comment_count'] ) );
  1105. }
  1106. }
  1107. }
  1108. return self::send_result( $todoinfo );
  1109. }
  1110. }
  1111. /**
  1112. * TODO取消关注
  1113. *
  1114. *
  1115. * @param string token , 必填
  1116. * @param string tid - TODO id , 必填
  1117. * @return todo array
  1118. * @author EasyChen
  1119. */
  1120. public function todo_unfollow()
  1121. {
  1122. $tid = intval(v('tid'));
  1123. if( $tid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TID') );
  1124. $sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1125. if( !$data = get_line( $sql ))
  1126. {
  1127. return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_EMPTY_RESULT_DATA') );
  1128. }
  1129. else
  1130. {
  1131. $sql = "DELETE FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' AND `is_follow` = 1 LIMIT 1";
  1132. run_sql( $sql );
  1133. if( db_errno() != 0 )
  1134. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1135. else
  1136. {
  1137. return self::send_result(get_todo_info_by_id( $tid , true ));
  1138. }
  1139. }
  1140. }
  1141. /**
  1142. * TODO添加关注
  1143. *
  1144. *
  1145. * @param string token , 必填
  1146. * @param string tid - TODO id , 必填
  1147. * @return todo array
  1148. * @author EasyChen
  1149. */
  1150. public function todo_follow()
  1151. {
  1152. $tid = intval(v('tid'));
  1153. if( $tid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TID') );
  1154. $sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1155. if( !$data = get_line( $sql ))
  1156. {
  1157. // 没数据正常的
  1158. $sql = "INSERT IGNORE INTO `todo_user` ( `uid` , `tid` , `status` , `is_follow` , `last_action_at` ) VALUES ( '" . intval( $_SESSION['uid'] ) . "' , '" . intval( $tid ) . "' , 1 , 1 , NOW() ) ";
  1159. run_sql( $sql );
  1160. if( db_errno() != 0 )
  1161. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1162. else
  1163. return self::send_result(get_todo_info_by_id( $tid , true ));
  1164. }
  1165. else
  1166. {
  1167. return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_TODO_ALREADY_FOLLOWED') );
  1168. }
  1169. }
  1170. /**
  1171. * TODO更新文字内容
  1172. *
  1173. *
  1174. * @param string token , 必填
  1175. * @param string tid - TODO id , 必填
  1176. * @param string text - TODO内容 , 必填
  1177. * @return todo array
  1178. * @author EasyChen
  1179. */
  1180. public function todo_update()
  1181. {
  1182. $tid = intval(v('tid'));
  1183. if( $tid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TID') );
  1184. // check user
  1185. //$sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1186. $sql = "SELECT * FROM `todo` WHERE `id` = '" . intval($tid) . "' AND `owner_uid` = '" . intval(uid()) . "' LIMIT 1";
  1187. if( !$data = get_line( $sql ))
  1188. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_UPDATE_OTHERS_TODO') );
  1189. $content = z(t(v('text')));
  1190. if( !not_empty($content) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TEXT') );
  1191. $sql = "UPDATE `todo` SET `content` = '" . s($content) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  1192. run_sql( $sql );
  1193. if( mysql_errno() != 0 )
  1194. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1195. else
  1196. {
  1197. run_sql( "UPDATE `todo_user` SET `last_action_at` = NOW() WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1");
  1198. return self::send_result(get_todo_info_by_id( $tid , true ));
  1199. }
  1200. }
  1201. /**
  1202. * 清除已经完成的单个TODO
  1203. *
  1204. *
  1205. * @param string token , 必填
  1206. * @param string tid - TODO id , 必填
  1207. * @return todo array
  1208. * @author EasyChen
  1209. */
  1210. public function todo_remove_done()
  1211. {
  1212. // @TODO clean all the info in other tables
  1213. $sql = "DELETE FROM `todo_user` WHERE `uid` = '" . intval($_SESSION['uid']) . "' AND `status` = 3 " ;
  1214. run_sql( $sql );
  1215. if( mysql_errno() != 0 )
  1216. {
  1217. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1218. }
  1219. else
  1220. return self::send_result( array('msg'=>'ok') );
  1221. }
  1222. /**
  1223. * 清除所有已经完成的TODO标记为
  1224. *
  1225. *
  1226. * @param string token , 必填
  1227. * @param string tid - TODO id , 必填
  1228. * @return todo array
  1229. * @author EasyChen
  1230. */
  1231. public function todo_all_done()
  1232. {
  1233. // @TODO clean all the info in other tables
  1234. $sql = "UPDATE `todo_user` SET `status` = 3 WHERE `uid` = '" . intval($_SESSION['uid']) . "' AND ( `status` = 1 OR `status` = 2 ) " ;
  1235. run_sql( $sql );
  1236. if( mysql_errno() != 0 )
  1237. {
  1238. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1239. }
  1240. else
  1241. return self::send_result( array('msg'=>'ok') );
  1242. }
  1243. /**
  1244. * 删除TODO
  1245. *
  1246. *
  1247. * @param string token , 必填
  1248. * @param string tid - TODO id , 必填
  1249. * @return todo array
  1250. * @author EasyChen
  1251. */
  1252. public function todo_remove()
  1253. {
  1254. $tid = intval(v('tid'));
  1255. if( $tid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TID') );
  1256. $old = get_todo_info_by_id( $tid );
  1257. $sql = "DELETE FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1258. run_sql( $sql );
  1259. if( mysql_errno() != 0 )
  1260. {
  1261. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1262. }
  1263. else
  1264. return self::send_result( $old );
  1265. }
  1266. /**
  1267. * 离线同步TODO
  1268. *
  1269. * 客户端用
  1270. * @ignore
  1271. */
  1272. public function todo_sync()
  1273. {
  1274. // 首先判断text是否存在
  1275. // 然后根据tid 判断是更新还是添加操作
  1276. //
  1277. $content = z(t(v('text')));
  1278. if( !not_empty( $content ) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TEXT') );
  1279. $tid = intval(v('tid'));
  1280. if( $tid < 0 )
  1281. {
  1282. if( intval(v('is_delete')) == 1 )
  1283. {
  1284. // 在本地添加后又在本地删除了
  1285. return self::send_result( array( 'msg' => __('API_MESSAGE_TODO_ALREADY_DELETE_LOCALLY') ) );
  1286. }
  1287. // add
  1288. return $this->todo_add();
  1289. }
  1290. else
  1291. {
  1292. // 鉴权
  1293. $sql = "SELECT * FROM `todo_user` WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1" ;
  1294. if( !$data = get_line( $sql ))
  1295. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_UPDATE_OTHERS_TODO') );
  1296. // 判断最后更新时间
  1297. //
  1298. // 服务器的最后操作时间 $data['last_action_at']
  1299. // 本地todo的最后操作时间
  1300. //
  1301. $client_last_action_at = z(t(v('last_action_at')));
  1302. if( not_empty( $data['last_action_at'] ) && not_empty( $client_last_action_at ) )
  1303. {
  1304. if( not_empty(v('client_now')) )
  1305. {
  1306. $offset = time() - strtotime( v('client_now') ) ;
  1307. }else $offset = 0;
  1308. // 客户端时间校正
  1309. // 你不能穿越时空
  1310. if( strtotime( v('last_action_at') ) > strtotime( v('client_now') ) )
  1311. $offset = 0;
  1312. if( strtotime( $client_last_action_at ) - strtotime( $data['last_action_at']) + $offset <= 0 )
  1313. return self::send_result( array( 'msg' => __('API_MESSAGE_TODO_ALREADY_HAD_OTHER_ACTION') ) );
  1314. }
  1315. // update
  1316. if( intval(v('is_delete')) == 1 )
  1317. {
  1318. // remove
  1319. $_REQUEST['tid'] = $tid;
  1320. return $this->todo_remove();
  1321. }
  1322. else
  1323. {
  1324. // update
  1325. // 先更新todo表
  1326. $sql = "UPDATE `todo` SET `content` = '" . s($content) . "' WHERE `id` = '" . intval($tid) . "' LIMIT 1";
  1327. run_sql( $sql );
  1328. $sql = "UPDATE `todo_user` SET
  1329. `is_star` = '" . intval( v('is_star') ) . "',
  1330. `is_public` = '" . intval( v('is_public') ) . "',
  1331. `status` = '" . intval( v('status') ) . "',
  1332. `last_action_at` = NOW() WHERE `tid` = '" . intval($tid) . "' AND `uid` = '" . intval($_SESSION['uid']) . "' LIMIT 1";
  1333. run_sql( $sql );
  1334. return self::send_result(get_todo_info_by_id( $tid , true ));
  1335. }
  1336. }
  1337. }
  1338. /**
  1339. * 发布广播
  1340. *
  1341. * 广播时如果不用@进行点名,则通知全部成员
  1342. *
  1343. * @param string text , 必填
  1344. * @param string type - user行为/主动广播 , 默认为主动广播
  1345. * @return todo array
  1346. * @author EasyChen
  1347. */
  1348. public function feed_publish()
  1349. {
  1350. $content = z(t(v('text')));
  1351. if( !not_empty($content) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TEXT'));
  1352. $reblog_id = intval(v('fid'));
  1353. switch( z(t(v('type'))) )
  1354. {
  1355. case 'user' :
  1356. $type = 3;
  1357. break;
  1358. case 'todo' :
  1359. $type = 2;
  1360. break;
  1361. case 'notice' :
  1362. $type = 1;
  1363. break;
  1364. case 'cast' :
  1365. default:
  1366. $type = 4;
  1367. }
  1368. $sql = "INSERT INTO `feed` ( `content` , `reblog_id` , `uid` , `timeline` , `type` ) VALUES ( '" . s($content) . "' , '" . intval( $reblog_id ) . "' , '" . intval( $_SESSION['uid'] ) . "' , NOW() , " . intval($type) . " )";
  1369. run_sql( $sql );
  1370. if( db_errno() != 0 )
  1371. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  1372. $lid = last_id();
  1373. if( intval($lid) < 1 )
  1374. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') );
  1375. if($feed = get_feed_by_id( $lid , db() ))
  1376. {
  1377. // feed 发布成功
  1378. // 当用户主动发布时,视为广播,检测at信息
  1379. if( $type == 4 )
  1380. {
  1381. if( $ats = find_at($content) )
  1382. {
  1383. $sql = "SELECT `id` FROM `user` WHERE (`level` > 0 AND `is_closed` != 1 ) ";
  1384. foreach( $ats as $at )
  1385. {
  1386. $at =z(t($at));
  1387. if( $gname = get_group_names() )
  1388. {
  1389. if( in_array(strtoupper($at),$gname) )
  1390. {
  1391. if( $ndata = get_group_unames($at) )
  1392. foreach( $ndata as $nname )
  1393. $names[] = $nname;
  1394. }else $names[] = $at;
  1395. }
  1396. else
  1397. {
  1398. $names[] = $at;
  1399. }
  1400. }
  1401. foreach( $names as $at )
  1402. {
  1403. $at =z(t($at));
  1404. if( mb_strlen($at, 'UTF-8') < 2 ) continue;
  1405. $wsql[] = " `name` = '" . s(t($at)) . "' ";
  1406. if( c('at_short_name') )
  1407. if( mb_strlen($at, 'UTF-8') == 2 )
  1408. $wsql[] = " `name` LIKE '_" . s($at) . "' ";
  1409. }
  1410. if( isset( $wsql ) && is_array( $wsql ) )
  1411. {
  1412. $sql = $sql . ' AND ( ' . join( ' OR ' , $wsql ) . ' ) ';
  1413. if( $udata = get_data( $sql ) )
  1414. foreach( $udata as $uitem )
  1415. $myuids[] = $uitem['id'];
  1416. if( isset( $myuids ) && is_array($myuids) )
  1417. {
  1418. $myuids = array_unique($myuids);
  1419. foreach( $myuids as $muid )
  1420. if( $muid != uid() )
  1421. send_notice( $muid , __('API_TEXT_AT_IN_CAST' , array( uname() , $content ) ) , 2 , array('fid'=>intval($lid) , 'count'=> $feed['comment_count'] ));
  1422. }
  1423. }
  1424. }
  1425. else
  1426. {
  1427. // 如果没有at,则认为是@全部人
  1428. $sql = "SELECT `id` FROM `user` WHERE `level` > 0 AND `is_closed` != 1 AND `id` !=" . intval(uid());
  1429. if( $udata = get_data( $sql ) )
  1430. {
  1431. foreach( $udata as $uitem )
  1432. $myuids[] = $uitem['id'];
  1433. if( isset( $myuids ) && is_array($myuids) )
  1434. {
  1435. $myuids = array_unique($myuids);
  1436. foreach( $myuids as $muid )
  1437. if( $muid != uid() )
  1438. send_notice( $muid, __('API_TEXT_ADD_CAST',array( uname() , $content )), 2 , array('fid'=>intval($lid) , 'count'=> $feed['comment_count'] ));
  1439. }
  1440. }
  1441. }
  1442. }
  1443. return self::send_result( $feed );
  1444. }
  1445. else
  1446. {
  1447. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  1448. }
  1449. }
  1450. /**
  1451. * 获取Feed列表
  1452. *
  1453. *
  1454. * @param string token , 必填
  1455. * @param string since_id - 最小TODO id
  1456. * @param string max_id - 最大TODO id
  1457. * @param string count - 每页TODO条数
  1458. * @param string ord - 排序 , asc 或者 desc
  1459. * @param string by - 排序字段
  1460. * @return feed list array
  1461. * @author EasyChen
  1462. */
  1463. public function feed_list()
  1464. {
  1465. $since_id = intval( v( 'since_id' ) );
  1466. $max_id = intval( v( 'max_id' ) );
  1467. $count = intval( v( 'count' ) );
  1468. $order = strtolower( z( t( v( 'ord' ) ) ) );
  1469. $by = strtolower( z( t( v( 'by' ) ) ) );
  1470. if( strlen($by) < 1 ) $by = 'id';
  1471. if( $order == 'asc' )
  1472. $ord = ' ASC ';
  1473. else
  1474. $ord = ' DESC ';
  1475. if( strlen( $by ) > 0 )
  1476. {
  1477. $osql = ' ORDER BY `' . s( $by ) . '` ' . $ord . ' ';
  1478. }
  1479. else
  1480. $osql = '';
  1481. if( $count < 1 ) $count = 10;
  1482. if( $count > 100 ) $count = 100;
  1483. if( $since_id > 0 )
  1484. {
  1485. $wsql = " AND `id` > '" . intval( $since_id ) . "' ";
  1486. }
  1487. elseif( $max_id > 0 )
  1488. {
  1489. $wsql = " AND `id` < '" . intval( $max_id ) . "' ";
  1490. }
  1491. else
  1492. {
  1493. $wsql = '';
  1494. }
  1495. $sql = "SELECT * FROM `feed` WHERE 1 ";
  1496. $sql = $sql . $wsql . $osql . " LIMIT " . $count ;
  1497. if( !$data = get_data( $sql ))
  1498. {
  1499. if( db_errno() == 0 )
  1500. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  1501. else
  1502. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  1503. }
  1504. else
  1505. {
  1506. $more = 1;
  1507. if( is_array( $data ) )
  1508. {
  1509. if( count($data) < $count ) $more = 0;
  1510. $first = reset( $data );
  1511. $max = $min = $first['id'];
  1512. foreach( $data as $hitem )
  1513. {
  1514. $huids[] = $hitem['uid'];
  1515. if( $hitem['id'] > $max ) $max = $hitem['id'];
  1516. if( $hitem['id'] < $min ) $min = $hitem['id'];
  1517. }
  1518. }
  1519. if( isset( $huids ) && is_array( $huids ) )
  1520. {
  1521. $sql = "SELECT " . USER_INFO . " FROM `user` WHERE `id` IN ( " . join( ' , ' , $huids ) . " ) ";
  1522. if($udata = get_data( $sql ))
  1523. {
  1524. foreach( $udata as $uitem )
  1525. {
  1526. if( strlen( $uitem['groups'] ) > 0 )
  1527. $uitem['groups'] = explode('|', trim( $uitem['groups'] , '|' )) ;
  1528. $uarray[$uitem['id']] = $uitem;
  1529. }
  1530. //print_r( $uarray );
  1531. if( isset( $uarray ) )
  1532. {
  1533. foreach( $data as $k=>$hitem )
  1534. {
  1535. if( isset( $uarray[$hitem['uid']] ) )
  1536. {
  1537. $data[$k]['user'] = $uarray[$hitem['uid']];
  1538. }
  1539. }
  1540. }
  1541. }
  1542. }
  1543. return self::send_result( array( 'max' => intval($max) , 'min' => intval($min) , 'items' => $data , 'more'=> intval( $more ) ) );
  1544. }
  1545. }
  1546. /**
  1547. * 删除Feed的评论
  1548. *
  1549. *
  1550. * @param string token , 必填
  1551. * @param string cid - 必填
  1552. * @return feed array
  1553. * @author EasyChen
  1554. */
  1555. public function feed_remove_comment( $cid = flase )
  1556. {
  1557. $cid = intval(v('cid'));
  1558. if( intval( $cid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','CID') );
  1559. $sql = "SELECT *,`id` as `cid` FROM `comment` WHERE `id` = '" . intval( $cid ) . "' LIMIT 1";
  1560. if( !$citem = get_line( $sql ) )
  1561. {
  1562. if( db_errno() != 0 )
  1563. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1564. else
  1565. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  1566. }
  1567. else
  1568. {
  1569. if( ($citem['uid'] != $_SESSION['uid']) && $_SESSION['level'] < 9 )
  1570. {
  1571. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_REMOVE_OTHERS_COMMENT') );
  1572. }
  1573. $sql = "DELETE FROM `comment` WHERE `id` = '" . intval($cid) . "' LIMIT 1";
  1574. run_sql( $sql );
  1575. // 更新feed评论计数
  1576. $fid = $citem['fid'];
  1577. $count = get_var( "SELECT COUNT(*) FROM `comment` WHERE `fid` = '" . intval($fid) . "' " , db()) ;
  1578. $sql = "UPDATE `feed` SET `comment_count` = '" . intval($count) . "' WHERE `id` = '" . intval($fid) . "' LIMIT 1";
  1579. run_sql( $sql );
  1580. if( db_errno() != 0 )
  1581. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1582. else
  1583. return self::send_result( $citem );
  1584. }
  1585. }
  1586. /**
  1587. * 删除Feed
  1588. *
  1589. *
  1590. * @param string token , 必填
  1591. * @param string fid - 必填
  1592. * @return feed array
  1593. * @author EasyChen
  1594. */
  1595. public function feed_remove( $fid = false )
  1596. {
  1597. if( !$fid ) $fid = intval(v('fid'));
  1598. if( intval( $fid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , 'FID NOT EXISTS' );
  1599. $finfo = get_line("SELECT * FROM `feed` WHERE `id` = '" . intval( $fid ) . "' LIMIT 1");
  1600. if( $finfo['uid'] != uid() && !is_admin() )
  1601. return self::send_error( LR_API_FORBIDDEN , __('API_MESSAGE_CANNOT_REMOVE_OTHERS_FEED') );
  1602. $sql = "DELETE FROM `feed` WHERE `id` = '" . intval( $fid ) . "' LIMIT 1";
  1603. run_sql( $sql );
  1604. $sql = "DELETE FROM `comment` WHERE `fid` = '" . intval( $fid ) . "'";
  1605. run_sql( $sql );
  1606. if( db_errno() != 0 )
  1607. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1608. else
  1609. return self::send_result( $finfo );
  1610. }
  1611. /**
  1612. * 为Feed添加评论
  1613. *
  1614. *
  1615. * @param string token , 必填
  1616. * @param string fid - 必填
  1617. * @param string text - 必填
  1618. * @return feed array
  1619. * @author EasyChen
  1620. */
  1621. public function feed_add_comment( $text = false , $fid = false )
  1622. {
  1623. if( !$text )
  1624. $content = $text = z(t(v('text')));
  1625. if( !not_empty($content) ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TEXT') );
  1626. if( !$fid )
  1627. $fid = intval(v('fid'));
  1628. if( intval( $fid ) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','FID') );
  1629. $finfo = get_line("SELECT * FROM `feed` WHERE `id` = '" . intval( $fid ) . "' LIMIT 1");
  1630. if( is_mobile_request() ) $device = 'mobile';
  1631. else $device = 'web';
  1632. $sql = "INSERT INTO `comment` ( `fid` , `uid` , `content` , `timeline` , `device` )
  1633. VALUES ( '" . intval($fid) . "' , '" . intval($_SESSION['uid']) . "' , '" . s( $content ) . "' , NOW() , '" . s($device) . "' ) ";
  1634. run_sql( $sql );
  1635. if( db_errno() != 0 )
  1636. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1637. else
  1638. {
  1639. $lid = last_id();
  1640. // feed表comment_count计数增加
  1641. $count = get_var( "SELECT COUNT(*) FROM `comment` WHERE `fid` = '" . intval($fid) . "' " , db()) ;
  1642. $sql = "UPDATE `feed` SET `comment_count` = '" . intval($count) . "' WHERE `id` = '" . intval($fid) . "' LIMIT 1";
  1643. run_sql( $sql );
  1644. // 向Feed作者发通知
  1645. if( $finfo['uid'] != uid() )
  1646. {
  1647. send_notice( $finfo['uid'] , __('API_TEXT_COMMENT_FEED_OWNED' , array( uname() , $finfo['content'] ,$content ) ) , 2 , array('fid'=>intval($fid) , 'count'=> $count ) );
  1648. }
  1649. // 向参与了该Feed讨论的同学发送通知
  1650. $sql = "SELECT `uid` FROM `comment` WHERE `fid`= '" . intval($fid) . "' ";
  1651. if( $uitems = get_data( $sql ) )
  1652. foreach( $uitems as $uitem )
  1653. {
  1654. if( $uitem['uid'] != uid() && $uitem['uid'] != $finfo['uid'] )
  1655. $myuids[] = $uitem['uid'];
  1656. }
  1657. if( isset($myuids) )
  1658. {
  1659. $myuids = array_unique($myuids);
  1660. foreach( $myuids as $muid )
  1661. {
  1662. send_notice( $muid , __('API_TEXT_COMMENT_FEED_IN' , array( uname() , $finfo['content'] , $content ) ) , 2 , array('fid'=>intval($fid) , 'count'=> $count ) );
  1663. }
  1664. }
  1665. // 向被@的同学,发送通知
  1666. if( $ats = find_at($content) )
  1667. {
  1668. $sql = "SELECT `id` FROM `user` WHERE ";
  1669. foreach( $ats as $at )
  1670. {
  1671. $at =z(t($at));
  1672. if( $gname = get_group_names() )
  1673. {
  1674. if( in_array(strtoupper($at),$gname) )
  1675. {
  1676. if( $ndata = get_group_unames($at) )
  1677. foreach( $ndata as $nname )
  1678. $names[] = $nname;
  1679. }else $names[] = $at;
  1680. }
  1681. else
  1682. {
  1683. $names[] = $at;
  1684. }
  1685. }
  1686. foreach( $names as $at )
  1687. {
  1688. $at =z(t($at));
  1689. if( mb_strlen($at, 'UTF-8') < 2 ) continue;
  1690. $wsql[] = " `name` = '" . s(t($at)) . "' ";
  1691. if( c('at_short_name') )
  1692. if( mb_strlen($at, 'UTF-8') == 2 )
  1693. $wsql[] = " `name` LIKE '_" . s($at) . "' ";
  1694. }
  1695. if( isset( $wsql ) && is_array( $wsql ) )
  1696. {
  1697. $sql = $sql . join( ' OR ' , $wsql );
  1698. if( $udata = get_data( $sql ) )
  1699. {
  1700. foreach( $udata as $uitem )
  1701. $myuids[] = $uitem['id'];
  1702. if( isset( $myuids ) && is_array( $myuids ) )
  1703. {
  1704. $myuids = array_unique( $myuids );
  1705. foreach( $myuids as $muid )
  1706. if( $muid != uid() && $muid != $finfo['uid'] )
  1707. send_notice( $muid , __('API_TEXT_AT_IN_CAST_COMMENT' , array( uname() , $finfo['content'] , $content ) ) , 2 , array('fid'=>intval($fid) , $count ));
  1708. }
  1709. }
  1710. }
  1711. }
  1712. if( $comment = get_line( "SELECT * FROM `comment` WHERE `id` = '" . intval($lid) . "' LIMIT 1" , db() ) )
  1713. {
  1714. $comment['user'] = get_user_info_by_id( $_SESSION['uid'] );
  1715. return self::send_result( $comment );
  1716. }
  1717. else
  1718. {
  1719. if( db_errno() != 0 )
  1720. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1721. else
  1722. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  1723. }
  1724. }
  1725. }
  1726. /**
  1727. * 读取Feed详细信息
  1728. *
  1729. *
  1730. * @param string token , 必填
  1731. * @param string fid - 必填
  1732. * @return feed array
  1733. * @author EasyChen
  1734. */
  1735. public function feed_detail()
  1736. {
  1737. $fid = intval(v('fid'));
  1738. if( $fid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','FID') );
  1739. $sql = "SELECT * FROM `feed` WHERE `id` = '" . intval($fid) . "' LIMIT 1" ;
  1740. if( !$data = get_line( $sql ) )
  1741. {
  1742. if( db_errno() != 0 )
  1743. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1744. else
  1745. return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  1746. }
  1747. else
  1748. {
  1749. // 添加feed的评论信息
  1750. $cdata = get_data( "SELECT * FROM `comment` WHERE `fid` = '" . intval($fid) . "' ORDER BY `timeline` DESC LIMIT 100" , $write_db );
  1751. if( is_array( $cdata ) )
  1752. foreach( $cdata as $citem )
  1753. {
  1754. $cuids[] = $citem['uid'];
  1755. }
  1756. if( isset( $cuids ) && is_array( $cuids ) )
  1757. {
  1758. $sql = "SELECT " . USER_INFO . " FROM `user` WHERE `id` IN ( " . join( ' , ' , $cuids ) . " ) ";
  1759. if($udata = get_data( $sql ))
  1760. {
  1761. foreach( $udata as $uitem )
  1762. {
  1763. if( strlen( $uitem['groups'] ) > 0 )
  1764. $uitem['groups'] = explode('|', trim( $uitem['groups'] , '|' )) ;
  1765. $uarray[$uitem['id']] = $uitem;
  1766. }
  1767. //print_r( $uarray );
  1768. if( isset( $uarray ) )
  1769. {
  1770. foreach( $cdata as $k=>$hitem )
  1771. {
  1772. if( isset( $uarray[$hitem['uid']] ) )
  1773. $cdata[$k]['user'] = $uarray[$hitem['uid']];
  1774. }
  1775. }
  1776. }
  1777. }
  1778. $data['comment'] = $cdata;
  1779. return self::send_result( $data );
  1780. }
  1781. }
  1782. /*
  1783. public function feed_remove()
  1784. {
  1785. $fid = intval(v('fid'));
  1786. if( $fid < 1 ) return self::send_error( LR_API_ARGS_ERROR , 'id FIELD REQUIRED' );
  1787. $sql = "SELECT * FROM `feed` WHERE `id` = '" . intval($fid) . "' LIMIT 1" ;
  1788. $data = get_line( $sql );
  1789. if( mysql_errno() != 0 )
  1790. {
  1791. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1792. }
  1793. $sql = "DELETE FROM `feed` WHERE `id` = '" . intval($fid) . "' LIMIT 1" ;
  1794. run_sql( $sql );
  1795. if( mysql_errno() != 0 )
  1796. {
  1797. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1798. }
  1799. else
  1800. return self::send_result( $data );
  1801. }*/
  1802. public function user_online()
  1803. {
  1804. // 5分钟内有过活动的都算
  1805. $sql = "SELECT `uid` , `last_active` , `device` , `place` FROM `online` WHERE `last_active` > '" . date( "Y-m-d H:i:s" , strtotime("-5 minutes") ) . "'";
  1806. if( !$data = get_data( $sql ) ) return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  1807. if( db_errno() != 0 )
  1808. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') );
  1809. else return self::send_result( $data );
  1810. }
  1811. /* ============ unread ================== */
  1812. /**
  1813. * 取得用户未读信息
  1814. *
  1815. *
  1816. * @param string token , 必填
  1817. * @return array ('notice'=>'未读计数' , 'nid' => '最后一条Notice ID' , 'text' => '最后一条未读Notice内容')
  1818. * @author EasyChen
  1819. */
  1820. public function user_unread()
  1821. {
  1822. // 处理掉全部的未读计数
  1823. // 私信和系统通知
  1824. $sql = "SELECT COUNT(*) FROM `notice` WHERE `to_uid` = '" . intval(uid()) . "' AND `is_read` = 0 ";
  1825. $notice_count = intval(get_var( $sql ));
  1826. $sql = "SELECT COUNT(*) FROM `message` WHERE `to_uid` = '" . intval(uid()) . "' AND `is_read` = 0 ";
  1827. $message_count = intval(get_var( $sql ));
  1828. $sql = "SELECT COUNT( * ) AS `from_cnt` , `from_uid` FROM `message` WHERE `to_uid` = '" . intval(uid()) . "' AND `is_read` = 0 GROUP BY `from_uid` ";
  1829. $muids = array();
  1830. $muidstring = '';
  1831. if( $mdata = get_data( $sql ) )
  1832. {
  1833. foreach( $mdata as $mitem )
  1834. {
  1835. $muids[] = $mitem['from_uid'];
  1836. }
  1837. $muidstring = join( '|' , $muids );
  1838. }
  1839. $last_notice = get_line( "SELECT * FROM `notice` WHERE `to_uid` = '" . intval(uid()) . "' AND `is_read` = 0 ORDER BY `id` DESC LIMIT 1" );
  1840. $last_message = get_line( "SELECT * FROM `message` WHERE `to_uid` = '" . intval(uid()) . "' AND `is_read` = 0 ORDER BY `id` DESC LIMIT 1" );
  1841. // update user online
  1842. $sql = "REPLACE `online` ( `uid` , `session` , `last_active` , `device` ) VALUES ( '" . intval(uid()) . "' , '" . s( session_id() ) . "' , NOW() , '" . get_device() . "' ) ";
  1843. run_sql($sql);
  1844. return self::send_result(
  1845. array(
  1846. 'all'=> $message_count+$notice_count,
  1847. 'message'=>$message_count,
  1848. 'uids'=>$muidstring,
  1849. 'notice'=>$notice_count,
  1850. 'nid'=>$last_notice['id'],
  1851. 'mid'=>$last_message['id'],
  1852. 'text'=>$last_notice['content']
  1853. ));
  1854. }
  1855. /**
  1856. * 获取Notice列表
  1857. *
  1858. *
  1859. * @param string token , 必填
  1860. * @param string since_id - 最小TODO id
  1861. * @param string max_id - 最大TODO id
  1862. * @param string count - 每页TODO条数
  1863. * @param string ord - 排序 , asc 或者 desc
  1864. * @param string by - 排序字段
  1865. * @return notice list array
  1866. * @author EasyChen
  1867. */
  1868. public function notice_list()
  1869. {
  1870. $since_id = intval( v( 'since_id' ) );
  1871. $max_id = intval( v( 'max_id' ) );
  1872. $count = intval( v( 'count' ) );
  1873. if( $count < 1 ) $count = 10;
  1874. if( $count > 100 ) $count = 100;
  1875. if( $since_id > 0 )
  1876. $wsql = " AND `id` > '" . intval( $since_id ) . "' ";
  1877. elseif( $max_id > 0 )
  1878. $wsql = " AND `id` < '" . intval( $max_id ) . "' ";
  1879. $osql = " ORDER BY `id` DESC ";
  1880. $sql = "SELECT * FROM `notice` WHERE `to_uid` = '" . intval(uid()) . "' ";
  1881. $sql = $sql . $wsql . $osql . " LIMIT " . $count ;
  1882. if( !$data = get_data( $sql ) ) return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  1883. if( db_errno() != 0 )
  1884. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') );
  1885. else
  1886. {
  1887. $more = 1;
  1888. if( is_array( $data ) )
  1889. {
  1890. if( count($data) < $count ) $more = 0;
  1891. $first = reset( $data );
  1892. $max = $min = $first['id'];
  1893. foreach( $data as $k=> $item )
  1894. {
  1895. if( $item['id'] > $max ) $max = $item['id'];
  1896. if( $item['id'] < $min ) $min = $item['id'];
  1897. if( strlen($item['data']) > 0 )
  1898. {
  1899. $data[$k]['data'] = unserialize( $item['data'] );
  1900. }
  1901. }
  1902. }
  1903. return self::send_result( array( 'max' => intval($max) , 'min' => intval($min) , 'items' => $data , 'more'=> intval( $more ) ) );
  1904. }
  1905. }
  1906. /**
  1907. * 标记notice为已读
  1908. *
  1909. *
  1910. * @param string token , 必填
  1911. * @param string nid - 选填,不指定是将当前用户全部notice标记为已读
  1912. * @return msg array ('msg'=>'done')
  1913. * @author EasyChen
  1914. */
  1915. public function notice_mark_read()
  1916. {
  1917. if( intval(v('nid')) < 1 )
  1918. $sql = "UPDATE `notice` SET `is_read` = 1 WHERE `to_uid` = '" . intval(uid()) . "'";
  1919. else
  1920. $sql = "UPDATE `notice` SET `is_read` = 1 WHERE `to_uid` = '" . intval(uid()) . "' AND `id` = '" . intval(v('nid')) . "' LIMIT 1";
  1921. run_sql( $sql );
  1922. if( db_errno() == 0 )
  1923. return self::send_result( array('msg'=>'done') );
  1924. else
  1925. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  1926. }
  1927. /**
  1928. * 用户更新头像
  1929. *
  1930. * 使用标准Form表单上传,头像文件名为file,只接受jpg格式的文件
  1931. *
  1932. * @param string token , 必填
  1933. * @return user array
  1934. * @author EasyChen
  1935. */
  1936. public function user_update_avatar()
  1937. {
  1938. if( $_FILES['file']['error'] != 0 )
  1939. return self::send_error( OP_API_UPLOAD_ERROR , 'UPLOAD ERROR ' . $_FILES['file']['error'] );
  1940. $tmp_image_name = SAE_TMP_PATH . md5(time().rand(1,99999)) . '.tmp.jpg';
  1941. jpeg_up( $_FILES['file']['tmp_name'], $tmp_image_name) ;
  1942. include_once( AROOT . 'lib/thumbnail.class.php' );
  1943. $file_thumb_name = 'avatar-' . uid(). '.jpg';
  1944. $tmp_file = SAE_TMP_PATH.$file_thumb_name;
  1945. include_once( AROOT . 'lib/icon.class.php' );
  1946. $icon = new Icon();
  1947. $icon->path = $tmp_image_name;
  1948. $icon->size = 100;
  1949. $icon->dest = $tmp_file;
  1950. $icon->createIcon();
  1951. if( on_sae() )
  1952. {
  1953. $s = new SaeStorage();
  1954. if(!$thumb_url = $s->write( 'upload' , $file_thumb_name , file_get_contents($tmp_file) ))
  1955. {
  1956. return self::send_error( OP_API_STORAGE_ERROR , 'SAVE ERROR ' . $s->errmsg() );
  1957. }
  1958. }
  1959. else
  1960. {
  1961. $local_storage = AROOT . 'static' . DS . 'upload' . DS . 'avatar' . DS ;
  1962. $local_storage_url = c('site_url') . DS . 'static' . DS . 'upload' . DS . 'avatar' . DS ;
  1963. $thumb_path = $local_storage . $file_thumb_name;
  1964. $thumb_url = $local_storage_url . $file_thumb_name;
  1965. if( !copy( $tmp_file , $thumb_path ) )
  1966. return self::send_error( OP_API_STORAGE_ERROR , 'SAVE ERROR ' );
  1967. }
  1968. $sql = "UPDATE `user` SET `avatar_small` = '" . s( $thumb_url ) . "' WHERE `id` = '" . intval(uid()) . "' LIMIT 1";
  1969. run_sql( $sql );
  1970. if( mysql_errno() != 0 )
  1971. {
  1972. return self::send_error( OP_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  1973. }
  1974. else
  1975. {
  1976. return self::send_result(get_user_info_by_id(intval(uid())));
  1977. }
  1978. }
  1979. /* ============ im =============== */
  1980. /**
  1981. * 向某个用户发送私信聊天
  1982. *
  1983. *
  1984. * @param string token , 必填
  1985. * @param string uid , 必填
  1986. * @param string text , 必填
  1987. * @return array( 'msg' => 'ok' )
  1988. * @author EasyChen
  1989. */
  1990. public function im_send( $uid = false , $text = false )
  1991. {
  1992. if( !$uid ) $uid = intval(v('uid'));
  1993. if( $uid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','UID'));
  1994. if( $uid == uid() ) return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_SPEAK_TO_SELF') );
  1995. if( !$text ) $text = z(t(v('text')));
  1996. if( strlen($text) < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','TEXT') );
  1997. $sql = "INSERT INTO `message` ( `from_uid` , `to_uid` , `timeline` , `content` ) VALUES ( '" . intval(uid()) . "'
  1998. , '" . intval($uid) . "' , NOW() , '" . s( $text ) . "' ) ";
  1999. run_sql( $sql );
  2000. if( mysql_errno() != 0 )
  2001. {
  2002. return self::send_error( OP_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  2003. }
  2004. else
  2005. {
  2006. return self::send_result( array( 'msg' => 'ok' ) );
  2007. }
  2008. }
  2009. /**
  2010. * 取得当前用户和指定用户聊天记录
  2011. *
  2012. * 不包含未读
  2013. *
  2014. * @param string token , 必填
  2015. * @param string uid , 必填
  2016. * @return im history data array
  2017. * @author EasyChen
  2018. */
  2019. public function im_history( $uid = false )
  2020. {
  2021. if( !$uid ) $uid = intval(v('uid'));
  2022. if( $uid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','UID') );
  2023. if( $uid == uid() ) return self::send_error( LR_API_ARGS_ERROR , __('API_MESSAGE_SPEAK_TO_SELF') );
  2024. $since_id = intval( v( 'since_id' ) );
  2025. $max_id = intval( v( 'max_id' ) );
  2026. $count = intval( v( 'count' ) );
  2027. if( $count < 1 ) $count = 10;
  2028. if( $count > 100 ) $count = 100;
  2029. /*
  2030. $all = intval(v('read_all'));
  2031. if( $all != 1 )
  2032. $wwsql = " AND `is_read` = 1 ";
  2033. else
  2034. $wwsql = "";
  2035. */
  2036. $wsql = '';
  2037. if( $since_id > 0 )
  2038. $wsql .= " AND `id` > '" . intval( $since_id ) . "' ";
  2039. elseif( $max_id > 0 )
  2040. $wsql .= " AND `id` < '" . intval( $max_id ) . "' ";
  2041. $word = z(t(v('word')));
  2042. if( strlen( $word ) > 0 ) $wsql .= $wsql . " AND `content` LIKE '%" . s($word) . "%' ";
  2043. $osql = " ORDER BY `id` DESC ";
  2044. $sql = "SELECT * FROM `message` WHERE 1 AND (( `from_uid` = '" . intval($uid) . "' AND `to_uid` = '" . uid() . "' ) ";
  2045. $sql .= " OR ( `from_uid` = '" . uid() . "' AND `to_uid` = '" . intval($uid) . "' )) ";
  2046. $sql = $sql . $wsql . $osql . " LIMIT " . $count ;
  2047. //sae_debug( 'sql=' . $sql );
  2048. if( !$data = get_data( $sql ) ) return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  2049. if( db_errno() != 0 )
  2050. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') );
  2051. else
  2052. {
  2053. $more = 1;
  2054. if( is_array( $data ) )
  2055. {
  2056. if( count($data) < $count ) $more = 0;
  2057. $first = reset( $data );
  2058. $max = $min = $first['id'];
  2059. foreach( $data as $k=> $item )
  2060. {
  2061. if( $item['id'] > $max ) $max = $item['id'];
  2062. if( $item['id'] < $min ) $min = $item['id'];
  2063. }
  2064. }
  2065. return self::send_result( array( 'max' => intval($max) , 'min' => intval($min) , 'items' => $data , 'more'=> intval( $more ) ) );
  2066. }
  2067. }
  2068. /**
  2069. * 取得当前用户和指定用户的未读私信消息
  2070. *
  2071. * 读取后自动标记为已读
  2072. *
  2073. * @param string token , 必填
  2074. * @param string uid , 必填
  2075. * @return im history data array
  2076. * @author EasyChen
  2077. */
  2078. public function get_fresh_chat()
  2079. {
  2080. $uid = intval(v('uid'));
  2081. if( $uid < 1 ) return self::send_error( LR_API_ARGS_ERROR , __('INPUT_CHECK_BAD_ARGS','UID') );
  2082. $since_id = intval(v('since_id'));
  2083. if( $since_id > 0 ) $wsql = "AND `id` > '" . $since_id . "' " ;
  2084. else $wsql = '';
  2085. $sql = "SELECT * FROM `message` WHERE `to_uid` = '" . intval(uid()) . "' AND `from_uid` = '" . intval($uid) . "' AND `is_read` = 0 " . $wsql . " ORDER BY `id` DESC LIMIT 100";
  2086. if( !$data = get_data( $sql ) ) return self::send_error( LR_API_DB_EMPTY_RESULT , __( 'API_MESSAGE_EMPTY_RESULT_DATA' ) );
  2087. if( db_errno() != 0 )
  2088. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') );
  2089. else
  2090. {
  2091. $more = 1;
  2092. if( is_array( $data ) )
  2093. {
  2094. if( count($data) < $count ) $more = 0;
  2095. $first = reset( $data );
  2096. $max = $min = $first['id'];
  2097. foreach( $data as $k=> $item )
  2098. {
  2099. if( $item['id'] > $max ) $max = $item['id'];
  2100. if( $item['id'] < $min ) $min = $item['id'];
  2101. }
  2102. }
  2103. $sql = "UPDATE `message` SET `is_read` = 1 WHERE `to_uid` = '" . intval(uid()) . "' AND `from_uid` = '" . intval($uid) . "' LIMIT 100";
  2104. run_sql( $sql );
  2105. return self::send_result( array( 'max' => intval($max) , 'min' => intval($min) , 'items' => $data , 'more'=> intval( $more ) ) );
  2106. }
  2107. }
  2108. /* ============ team =============== */
  2109. /**
  2110. * 创建激活码
  2111. *
  2112. * 普通成员通过创建激活码,邀请其他用户注册
  2113. *
  2114. * @param string token , 必填
  2115. * @return array('activecode'=>$string)
  2116. * @author EasyChen
  2117. */
  2118. public function team_activecode()
  2119. {
  2120. $string = substr(md5(rand( 1000 , 9999 ) . time()) , 0 , 4 );
  2121. //$string = md5(rand( 1000 , 9999 ) . time());
  2122. $sql = "REPLACE INTO `activecode` ( `code` , `creator_uid` , `timeline` ) VALUES ( '" . s($string) . "' , '" . uid() . "' , NOW() )";
  2123. run_sql( $sql );
  2124. if( db_errno() != 0 )
  2125. {
  2126. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . db_error() );
  2127. }
  2128. else
  2129. {
  2130. return self::send_result( array('activecode'=>$string) );
  2131. }
  2132. }
  2133. /**
  2134. * 团队成员列表
  2135. *
  2136. * 不包含密码信息
  2137. *
  2138. * @param string token , 必填
  2139. * @return user list array
  2140. * @author EasyChen
  2141. */
  2142. public function team_members()
  2143. {
  2144. $sql = "SELECT * FROM `user` WHERE `is_closed` = 0 LIMIT 500";
  2145. if( !$data = get_data( $sql ) )
  2146. {
  2147. if( db_errno() == 0 )
  2148. return self::send_error( LR_API_DB_EMPTY_RESULT , __('API_MESSAGE_EMPTY_RESULT_DATA') );
  2149. else
  2150. return self::send_error( LR_API_DB_ERROR , __('API_MESSAGE_DATABASE_ERROR') . mysql_error() );
  2151. }
  2152. // clean password field
  2153. foreach( $data as $k=>$v )
  2154. {
  2155. $data[$k]['password'] = null;
  2156. unset($data[$k]['password']);
  2157. if( strlen($data[$k]['groups']) > 0 ) $data[$k]['groups'] = explode('|', trim( $data[$k]['groups'] , '|' )) ;
  2158. }
  2159. return self::send_result( $data );
  2160. }
  2161. /* ============ groups =============== */
  2162. /**
  2163. * 分组列表
  2164. *
  2165. * 显示所有分组名
  2166. *
  2167. * @param string token , 必填
  2168. * @return group array
  2169. * @author EasyChen
  2170. */
  2171. public function groups()
  2172. {
  2173. return self::send_result( get_group_names() );
  2174. }
  2175. /*
  2176. * ignore
  2177. */
  2178. private function check_token()
  2179. {
  2180. $token = z( t( v( 'token' ) ) );
  2181. if( strlen( $token ) < 2 )
  2182. {
  2183. return self::send_error( LR_API_TOKEN_ERROR , 'NO TOKEN' );
  2184. }
  2185. session_id( $token );
  2186. session_set_cookie_params( c('session_time') );
  2187. @session_start();
  2188. if( $_SESSION[ 'token' ] != $token )
  2189. {
  2190. return self::send_error( LR_API_TOKEN_ERROR , 'BAD TOKEN' );
  2191. }
  2192. }
  2193. /*
  2194. * ignore
  2195. */
  2196. public static function send_error( $number , $msg )
  2197. {
  2198. $obj = array();
  2199. $obj[ 'err_code' ] = intval( $number );
  2200. $obj[ 'err_msg' ] = $msg;
  2201. if( g('API_EMBED_MODE') == 1 )
  2202. return json_encode( $obj );
  2203. else
  2204. {
  2205. header('Content-type: application/json');
  2206. die( json_encode( $obj ) );
  2207. }
  2208. }
  2209. /*
  2210. * ignore
  2211. */
  2212. public static function send_result( $data )
  2213. {
  2214. $data = apply_filter( 'API_' . g('a') .'_OUTPUT_FILTER' , $data );
  2215. $obj = array();
  2216. $obj[ 'err_code' ] = '0';
  2217. $obj[ 'err_msg' ] = 'success';
  2218. $obj[ 'data' ] = $data;
  2219. if( g('API_EMBED_MODE') == 1 )
  2220. return json_encode( $obj );
  2221. else
  2222. {
  2223. header('Content-type: application/json');
  2224. die( json_encode( $obj ) );
  2225. }
  2226. }
  2227. }
  2228. ?>