Config.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. <?php
  2. namespace App\Http\Controllers\admin;
  3. use Illuminate\Http\JsonResponse;
  4. use App\Constants\HttpStatus;
  5. use App\Http\Controllers\Controller;
  6. use App\Models\Config as ConfigModel;
  7. use Illuminate\Support\Facades\Cache;
  8. use Illuminate\Support\Facades\DB;
  9. use Illuminate\Validation\ValidationException;
  10. use Exception;
  11. use Telegram\Bot\Api;
  12. use Telegram\Bot\Exceptions\TelegramSDKException;
  13. use Telegram\Bot\FileUpload\InputFile;
  14. use App\Services\ConfigService;
  15. class Config extends Controller
  16. {
  17. /**
  18. */
  19. public function setField()
  20. {
  21. try {
  22. $params = request()->validate([
  23. 'field' => ['required', 'string', 'max:255'],
  24. 'val' => ['nullable'],
  25. 'remark' => ['nullable'],
  26. ]);
  27. $val = $params['val'] ?? '';
  28. $update_data=[
  29. 'val' => $val,
  30. ];
  31. if (isset($params['remark'])) {
  32. $update_data['remark'] = $params['remark'];
  33. }
  34. ConfigModel::updateOrCreate(['field' => $params['field']], $update_data);
  35. } catch (ValidationException $e) {
  36. return $this->error(HttpStatus::VALIDATION_FAILED, $e->validator->errors()->first());
  37. } catch (Exception $e) {
  38. return $this->error(intval($e->getCode()));
  39. }
  40. return $this->success();
  41. }
  42. /**
  43. * @api {post} /admin/config/pc28Switch 游戏切换(0:pc28 1:急速28)
  44. * @apiGroup 配置
  45. * @apiUse result
  46. * @apiUse header
  47. * @apiVersion 1.0.0
  48. *
  49. * @apiParam {int=0,1} val (0:pc28 1:极速28)
  50. */
  51. public function pc28Switch()
  52. {
  53. try {
  54. $params = request()->validate([
  55. 'val' => ['required', 'integer', 'min:0', 'in:0,1']
  56. ]);
  57. ConfigModel::updateOrCreate(['field' => 'pc28_switch'], ['val' => $params['val']]);
  58. Cache::put('pc28_switch', $params['val']);
  59. } catch (ValidationException $e) {
  60. return $this->error(HttpStatus::VALIDATION_FAILED, $e->validator->errors()->first());
  61. } catch (Exception $e) {
  62. return $this->error(intval($e->getCode()));
  63. }
  64. return $this->success();
  65. }
  66. /**
  67. * @api {get} /admin/config/pcConfig 极速PC28相关配置
  68. * @apiGroup 配置
  69. * @apiUse result
  70. * @apiUse header
  71. * @apiVersion 1.0.0
  72. *
  73. * @apiParam {int} [page=1]
  74. * @apiParam {int} [limit=15]
  75. */
  76. public function pcConfig(): JsonResponse
  77. {
  78. try {
  79. $search['group_id'] = 4;
  80. $result = ConfigService::paginate($search);
  81. foreach ($result['data'] as $item) {
  82. if ($item['field'] == 'pc28_switch') {
  83. $item['val'] = Cache::get('pc28_switch', $item['val']);
  84. }
  85. }
  86. } catch (ValidationException $e) {
  87. return $this->error(HttpStatus::VALIDATION_FAILED, $e->validator->errors()->first());
  88. } catch
  89. (Exception $e) {
  90. return $this->error(intval($e->getCode()));
  91. }
  92. return $this->success($result);
  93. }
  94. /**
  95. * 分页数据
  96. *
  97. */
  98. function index()
  99. {
  100. try {
  101. request()->validate([
  102. 'field' => ['nullable', 'string'],
  103. 'id' => ['nullable', 'string'],
  104. ]);
  105. $search = request()->all();
  106. $search['in_group_id'] = [1, 3];
  107. $result = ConfigService::paginate($search);
  108. } catch (ValidationException $e) {
  109. return $this->error(HttpStatus::VALIDATION_FAILED, $e->validator->errors()->first());
  110. } catch (Exception $e) {
  111. return $this->error(intval($e->getCode()));
  112. }
  113. return $this->success($result);
  114. }
  115. /**
  116. * 修改|新增
  117. *
  118. */
  119. public
  120. function store()
  121. {
  122. try {
  123. $id = request()->post('id', '');
  124. if ($id) {
  125. $validator = [
  126. 'id' => ['required', 'integer', 'min:1'],
  127. 'val' => ['required', 'string'],
  128. 'remark' => 'required|nullable|string',
  129. ];
  130. } else {
  131. $validator = [
  132. 'field' => 'required|string|max:50|alpha_dash|unique:config,field',
  133. 'val' => 'required|string',
  134. 'remark' => 'required|nullable|string',
  135. ];
  136. $field = request()->input("field", 'aaa');
  137. switch ($field) {
  138. case 'group_language':
  139. $validator['val'] = ['required', 'string', 'in:zh,vi,en'];
  140. break;
  141. case 'pc28_switch':
  142. $validator['val'] = ['required', 'integer', 'in:0,1'];
  143. break;
  144. case 'pc28_time':
  145. //格式如:09:00-21:00
  146. $validator['val'] = ['nullable', 'string', 'regex:/^\d{2}:\d{2}-\d{2}:\d{2}$/i'];
  147. break;
  148. }
  149. }
  150. $params = request()->validate($validator);
  151. if (!isset($params['id'])) $params['group_id'] = 3;
  152. $ret = ConfigService::submit($params);
  153. if ($ret['code'] == ConfigService::NOT) {
  154. throw new Exception(HttpStatus::CUSTOM_ERROR, $ret['code']);
  155. }
  156. } catch (ValidationException $e) {
  157. return $this->error(HttpStatus::CUSTOM_ERROR, $e->validator->errors()->first());
  158. } catch (Exception $e) {
  159. return $this->error(intval($e->getCode()));
  160. }
  161. return $this->success([], $ret['msg']);
  162. }
  163. /**
  164. * 删除
  165. */
  166. public
  167. function destroy()
  168. {
  169. $id = request()->post('id');
  170. // 示例:通过 ID 删除
  171. $info = ConfigService::findOne(['id' => $id]);
  172. if (!$info) {
  173. return $this->error(HttpStatus::CUSTOM_ERROR, '配置不存在');
  174. }
  175. if ($info->group_id !== 3) {
  176. return $this->error(HttpStatus::CUSTOM_ERROR, '禁止删除');
  177. }
  178. $info->delete();
  179. return $this->success([], '删除成功');
  180. }
  181. /**
  182. * @api {get} /admin/config/get 获取指定配置
  183. * @apiGroup 配置
  184. * @apiUse result
  185. * @apiUse header
  186. * @apiVersion 1.0.0
  187. *
  188. * @apiParam {string} field 配置项
  189. * - base_score 房间底分数组
  190. * - brokerage 抽佣比例
  191. * - service_charge 提现手续费
  192. * - service_account 客服账号
  193. * - receiving_address 手动收款 的地址
  194. * - receiving_type 收款方式 1-自动 2-手动
  195. * - channel_message 频道消息
  196. *
  197. * @apiSuccess (data) {Object} data
  198. * @apiSuccess (data) {int[]} [data.base_score] 房间底分数组
  199. * @apiSuccess (data) {float} [data.brokerage] 抽佣比例
  200. * @apiSuccess (data) {int} [data.service_charge] 提现手续费
  201. * @apiSuccess (data) {string} [data.service_account] 客服账号
  202. * @apiSuccess (data) {string} [data.receiving_address] 手动收款 的地址
  203. * @apiSuccess (data) {int} [data.receiving_type] 收款方式 1-自动 2-手动
  204. * @apiSuccess (data) {Object} [data.channel_message] 频道消息
  205. * @apiSuccess (data) {string} data.channel_message.chatId 频道账号或频道ID
  206. * @apiSuccess (data) {string} data.channel_message.image 要发送频道消息 的图片URL
  207. * @apiSuccess (data) {string} data.channel_message.text 要发送频道消息文 的本内容
  208. * @apiSuccess (data) {array} data.channel_message.button 要发送频道消息 的内联按钮,具体结构见下方
  209. * @apiSuccessExample {js} 内联按钮结构
  210. * //button 的数据格式如下
  211. * [
  212. * [ //第一行
  213. * { //第一行按钮 的第一个按钮
  214. * "text": "百度", //按钮文字
  215. * "url": "https://baidu.com" //按钮跳转的链接
  216. * },
  217. * { //第一行按钮 的第二个按钮
  218. * "text": "百度",
  219. * "url": "https://baidu.com"
  220. * }
  221. * //更多按钮...
  222. * ],
  223. * [ //第二行
  224. * {
  225. * "text": "百度",
  226. * "url": "https://baidu.com"
  227. * }
  228. * ]
  229. * //更多行...
  230. * ]
  231. *
  232. */
  233. public function get()
  234. {
  235. try {
  236. request()->validate([
  237. 'field' => ['required', 'string', 'min:1'],
  238. ]);
  239. $field = request()->input('field');
  240. $config = ConfigModel::where('field', $field)->first();
  241. $res = [];
  242. if ($config) {
  243. $val = $config->val;
  244. switch ($field) {
  245. case "channel_message":
  246. case "base_score":
  247. $val = json_decode($config->val);
  248. break;
  249. case "brokerage":
  250. case "service_charge":
  251. $val = floatval($config->val);
  252. break;
  253. }
  254. $res[$field] = $val;
  255. }
  256. } catch (ValidationException $e) {
  257. return $this->error(HttpStatus::CUSTOM_ERROR, $e->validator->errors()->first());
  258. } catch (Exception $e) {
  259. return $this->error(intval($e->getCode()));
  260. }
  261. return $this->success($res);
  262. }
  263. /**
  264. * @api {get} /admin/config/getAll 获取所有配置
  265. * @apiGroup 配置
  266. * @apiUse result
  267. * @apiUse header
  268. * @apiVersion 1.0.0
  269. */
  270. public
  271. function getAll()
  272. {
  273. $list = ConfigModel::where('id', '>', 0)->get();
  274. $arr = [];
  275. foreach ($list as $item) {
  276. $val = $item['val'];
  277. switch ($item['field']) {
  278. case "channel_message":
  279. case "base_score":
  280. $val = json_decode($item['val'], true);
  281. break;
  282. case "brokerage":
  283. case "service_charge":
  284. $val = floatval($item['val']);
  285. break;
  286. }
  287. $arr[$item['field']] = $val;
  288. }
  289. return $this->success($arr);
  290. }
  291. /**
  292. * @api {post} /admin/config/sendChannelMessage 发送频道消息
  293. * @apiGroup 配置
  294. * @apiUse result
  295. * @apiUse header
  296. * @apiVersion 1.0.0
  297. * @apiDescription 该接口会保存配置,并发送频道消息; 创建频道之后需要将 bot 拉进频道内,然后将 bot 设置为管理员
  298. *
  299. *
  300. * @apiParam {String} chatId 频道的username - 创建频道时候填写的 username
  301. * @apiParam {String} type 发送的类型 - image:图片 - video:视频
  302. * @apiParam {String} image 要发送的图片
  303. * @apiParam {String} text 要发送的文字
  304. * @apiParam {Array} button 消息中的按钮 具体结构请看示例代码
  305. * @apiParam {String} video 视频
  306. * @apiParam {String} video_caption 视频文案
  307. * @apiParam {Boolean} [isSend=true] 是否发送
  308. * @apiParam {Boolean} [isTop=true] 是否置顶
  309. */
  310. public function sendChannelMessage()
  311. {
  312. set_time_limit(0);
  313. DB::beginTransaction();
  314. try {
  315. $validate = [
  316. 'chatId' => ['required', 'string', 'min:1'],
  317. 'type' => ['required', 'string', 'in:image,video,text'],
  318. 'text' => ['nullable', 'string'],
  319. 'isSend' => ['nullable', 'boolean'],
  320. 'isTop' => ['nullable', 'boolean'],
  321. 'button' => ['array'],
  322. 'button.*' => ['required', 'array'],
  323. 'button.*.*.text' => ['required', 'string'],
  324. 'button.*.*.url' => ['required', 'url'],
  325. ];
  326. $type = request()->input('type');
  327. if (in_array($type, ['image', 'video'])) $validate[$type] = ['required', 'url'];
  328. $params = request()->validate($validate);
  329. $params['image'] = request()->input('image', '');
  330. $params['video'] = request()->input('video', '');
  331. $isSend = request()->input('isSend', false);
  332. $isTop = request()->input('isTop', false);
  333. unset($params['isTop'], $params['isSend']);
  334. ConfigModel::where('field', 'channel_message')->update(['val' => json_encode($params)]);
  335. DB::commit();
  336. } catch (ValidationException $e) {
  337. DB::rollBack();
  338. return $this->error(HttpStatus::CUSTOM_ERROR, $e->validator->errors()->first());
  339. } catch (Exception $e) {
  340. DB::rollBack();
  341. return $this->error(intval($e->getCode()), $e->getMessage());
  342. }
  343. if ($isSend) {
  344. try {
  345. $config = ConfigModel::where('field', 'channel_message')->first()->val;
  346. $config = json_decode($config, true);
  347. $telegram = new Api(config('services.telegram.token'));
  348. $msg = [];
  349. $msg['chat_id'] = "@{$config['chatId']}";
  350. $msg['protect_content'] = false;
  351. if (!empty($config['button'])) {
  352. $msg['reply_markup'] = json_encode(['inline_keyboard' => $config['button']]);
  353. }
  354. switch ($type) {
  355. case 'image':
  356. $msg['photo'] = InputFile::create($config['image']);
  357. $msg['caption'] = $config['text'];
  358. $response = $telegram->sendPhoto($msg);
  359. break;
  360. case 'video':
  361. $msg['video'] = InputFile::create($config['video']);
  362. $msg['caption'] = $config['text'];
  363. $response = $telegram->sendVideo($msg);
  364. break;
  365. case 'text':
  366. $msg['text'] = $config['text'];
  367. $response = $telegram->sendMessage($msg);
  368. break;
  369. default:
  370. throw new Exception("保存成功,发送失败", HttpStatus::CUSTOM_ERROR);
  371. }
  372. // 置顶消息
  373. if ($isTop) {
  374. $messageId = $response->get('message_id');
  375. $telegram->pinChatMessage(['chat_id' => "@{$config['chatId']}", 'message_id' => $messageId]);
  376. }
  377. } catch (TelegramSDKException $e) {
  378. return $this->error(HttpStatus::CUSTOM_ERROR, '保存成功,发送失败', $e->getMessage());
  379. } catch (Exception $e) {
  380. return $this->error($e->getCode(), '保存成功,发送失败');
  381. }
  382. }
  383. return $this->success();
  384. }
  385. /**
  386. * @api {post} /admin/config/set 修改配置
  387. * @apiGroup 配置
  388. * @apiUse result
  389. * @apiUse header
  390. * @apiVersion 1.0.0
  391. *
  392. * @apiParam {int[]} base_score 房间底分数组
  393. * @apiParam {string} brokerage 抽佣比例
  394. * @apiParam {string} service_charge 提现手续费
  395. * @apiParam {string} service_account 客服账号
  396. * @apiParam {string} receiving_address 充值收款地址
  397. * @apiParam {string} receiving_type 收款方式 1-自动 2-手动
  398. *
  399. */
  400. public function set()
  401. {
  402. DB::beginTransaction();
  403. try {
  404. request()->validate([
  405. 'base_score' => ['required', 'array', 'min:1', 'max:30'],
  406. 'base_score.*' => ['integer', 'min:1'],
  407. 'brokerage' => ['required', 'numeric', 'min:0.01', 'max:1', 'regex:/^\d*(\.\d{1,2})?$/'],
  408. 'service_charge' => ['required', 'integer', 'min:1'],
  409. 'service_account' => ['required', 'string', 'min:1'],
  410. 'receiving_address' => ['required', 'string', 'min:34'],
  411. 'receiving_type' => ['required', 'integer', 'in:1,2']
  412. ]);
  413. $baseScore = request()->input('base_score');
  414. sort($baseScore);
  415. $baseScore = array_unique($baseScore);
  416. ConfigModel::where('field', 'base_score')
  417. ->update(['val' => json_encode($baseScore)]);
  418. $val = request()->input('brokerage');
  419. ConfigModel::where('field', 'brokerage')
  420. ->update(['val' => $val]);
  421. $val = request()->input('service_charge');
  422. ConfigModel::where('field', 'service_charge')
  423. ->update(['val' => $val]);
  424. $val = request()->input('service_account');
  425. ConfigModel::where('field', 'service_account')
  426. ->update(['val' => $val]);
  427. $val = request()->input('receiving_address');
  428. ConfigModel::where('field', 'receiving_address')
  429. ->update(['val' => $val]);
  430. $val = request()->input('receiving_type');
  431. ConfigModel::where('field', 'receiving_type')
  432. ->update(['val' => $val]);
  433. DB::commit();
  434. } catch (ValidationException $e) {
  435. DB::rollBack();
  436. return $this->error(HttpStatus::CUSTOM_ERROR, $e->validator->errors()->first());
  437. } catch (Exception $e) {
  438. DB::rollBack();
  439. return $this->error(intval($e->getCode()), $e->getMessage());
  440. }
  441. return $this->success();
  442. }
  443. }